Sfoglia il codice sorgente

Merge branch 'develop3.0-tmd' of http://106.12.23.251:10080/TEAMMODEL/TEAMModelOS into develop3.0-tmd

zhouj1203@hotmail.com 4 anni fa
parent
commit
366a19d657
72 ha cambiato i file con 2707 aggiunte e 2567 eliminazioni
  1. 218 0
      TEAMModelFunction/ExamTrigger.cs
  2. 4 303
      TEAMModelFunction/MonitorCosmosDB.cs
  3. 79 0
      TEAMModelFunction/SurveyTrigger.cs
  4. 79 0
      TEAMModelFunction/VoteTrigger.cs
  5. 20 18
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactory.cs
  6. 5 0
      TEAMModelOS.SDK/Extension/Utils.cs
  7. 21 0
      TEAMModelOS.SDK/Models/Cosmos/Common/CommonData.cs
  8. 22 21
      TEAMModelOS.SDK/Models/Cosmos/School/Vote.cs
  9. 46 0
      TEAMModelOS/ClientApp/src/assets/iconfont/demo_index.html
  10. 14 6
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.css
  11. BIN
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.eot
  12. 1 1
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.js
  13. 14 0
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.json
  14. 6 0
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.svg
  15. BIN
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.ttf
  16. BIN
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff
  17. BIN
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff2
  18. 12 4
      TEAMModelOS/ClientApp/src/common/BaseCanvas.vue
  19. 2 0
      TEAMModelOS/ClientApp/src/common/BaseMyCanvas.vue
  20. 1 1
      TEAMModelOS/ClientApp/src/common/BaseUserPoptip.vue
  21. 6 14
      TEAMModelOS/ClientApp/src/components/evaluation/ExerciseList.vue
  22. 16 0
      TEAMModelOS/ClientApp/src/components/questionnaire/BaseQnForm.less
  23. 34 8
      TEAMModelOS/ClientApp/src/components/questionnaire/BaseQnForm.vue
  24. 1 8
      TEAMModelOS/ClientApp/src/components/selflearn/ExerciseList.vue
  25. 2 2
      TEAMModelOS/ClientApp/src/components/selflearn/NewChooseContent.vue
  26. 3 3
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContent.vue
  27. 298 296
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReport.vue
  28. 7 3
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReportCharts/KeyPointPerformChart.vue
  29. 6 3
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReportCharts/RecognizePerformChart.vue
  30. 39 7
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestPop.vue
  31. 15 21
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTest.vue
  32. 2 18
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/composePaper.vue
  33. 0 29
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventList.vue
  34. 13 7
      TEAMModelOS/ClientApp/src/components/vote/BaseVoteForm.vue
  35. 0 2
      TEAMModelOS/ClientApp/src/store/module/studentWeb.js
  36. 3 4
      TEAMModelOS/ClientApp/src/utils/editorTools.js
  37. 14 1
      TEAMModelOS/ClientApp/src/utils/evTools.js
  38. 5 7
      TEAMModelOS/ClientApp/src/view/classrecord/ClassRecord.vue
  39. 20 22
      TEAMModelOS/ClientApp/src/view/evaluation/bank/ExerciseList.vue
  40. 3 0
      TEAMModelOS/ClientApp/src/view/evaluation/bank/TestPaperList.vue
  41. 5 10
      TEAMModelOS/ClientApp/src/view/evaluation/components/BaseChild.vue
  42. 1 3
      TEAMModelOS/ClientApp/src/view/evaluation/components/BaseCreateChild.vue
  43. 1 3
      TEAMModelOS/ClientApp/src/view/evaluation/components/BaseEditExercise.vue
  44. 2 7
      TEAMModelOS/ClientApp/src/view/evaluation/components/BaseExerciseList.vue
  45. 2 1
      TEAMModelOS/ClientApp/src/view/evaluation/index/CreateExercises.less
  46. 1 3
      TEAMModelOS/ClientApp/src/view/evaluation/index/CreateExercises.vue
  47. 65 269
      TEAMModelOS/ClientApp/src/view/evaluation/types/BaseCompletion.vue
  48. 1 1
      TEAMModelOS/ClientApp/src/view/evaluation/types/BaseCompose.vue
  49. 1 1
      TEAMModelOS/ClientApp/src/view/evaluation/types/BaseJudge.vue
  50. 3 3
      TEAMModelOS/ClientApp/src/view/evaluation/types/BaseMultiple.vue
  51. 4 4
      TEAMModelOS/ClientApp/src/view/evaluation/types/BaseSingle.vue
  52. 1 5
      TEAMModelOS/ClientApp/src/view/evaluation/types/BaseSubjective.vue
  53. 17 6
      TEAMModelOS/ClientApp/src/view/learnactivity/AutoCreateNew.vue
  54. 35 0
      TEAMModelOS/ClientApp/src/view/learnactivity/ManageEvaluation.less
  55. 326 298
      TEAMModelOS/ClientApp/src/view/learnactivity/ManageEvaluation.vue
  56. 8 2
      TEAMModelOS/ClientApp/src/view/learnactivity/ManualCreate.vue
  57. 87 4
      TEAMModelOS/ClientApp/src/view/learnactivity/PaperScore.less
  58. 168 82
      TEAMModelOS/ClientApp/src/view/learnactivity/PaperScore.vue
  59. 16 0
      TEAMModelOS/ClientApp/src/view/learnactivity/Scoring.less
  60. 106 43
      TEAMModelOS/ClientApp/src/view/learnactivity/Scoring.vue
  61. 1 1
      TEAMModelOS/ClientApp/src/view/login/Index.less
  62. 698 841
      TEAMModelOS/ClientApp/src/view/student-account/Index.vue
  63. 12 1
      TEAMModelOS/ClientApp/src/view/teachcontent/index.vue
  64. 2 2
      TEAMModelOS/ClientApp/src/view/teachermgmt/components/userList/Index.vue
  65. 3 3
      TEAMModelOS/Controllers/Common/ExamController.cs
  66. 57 55
      TEAMModelOS/Controllers/Common/VoteController.cs
  67. 11 6
      TEAMModelOS/Controllers/Item/ItemController.cs
  68. 35 59
      TEAMModelOS/Controllers/School/StudentController.cs
  69. 1 1
      TEAMModelOS/Controllers/Teacher/InitController.cs
  70. 0 5
      TEAMModelOS/Models/Dto/VoteDto.cs
  71. 0 37
      TEAMModelOS/Models/Dto/VoteStudentDto.cs
  72. 6 2
      TEAMModelOS/TEAMModelOS.csproj

+ 218 - 0
TEAMModelFunction/ExamTrigger.cs

@@ -0,0 +1,218 @@
+using Azure.Cosmos;
+using Azure.Messaging.ServiceBus;
+using Microsoft.Azure.Documents;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Models;
+
+namespace TEAMModelFunction
+{
+    public class ExamTrigger
+    {
+        public static async void Trigger(AzureCosmosFactory _azureCosmos, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, DingDing _dingDing, 
+            CosmosClient client, Document input ,string code,long stime,long etime, string school)
+        {
+            ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(input.Id, new Azure.Cosmos.PartitionKey($"{code}"));
+            List<ExamClassResult> examClassResults = new List<ExamClassResult>();
+            List<ExamSubject> examSubjects = new List<ExamSubject>();
+            await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select value(c) from c where c.examId = '{info.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"ExamClassResult-{school}") }))
+            {
+                using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                {
+                    foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                    {
+                        examClassResults.Add(obj.ToObject<ExamClassResult>());
+                    }
+                }
+            }
+
+            List<ChangeRecord> records = await _azureStorage.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", input.Id }, { "PartitionKey", info.progress } });
+            //ChangeRecord record = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ChangeRecord>(input.Id, new Azure.Cosmos.PartitionKey($"{info.progress}"));
+            switch (info.progress)
+            {
+                case "pending":
+                    var message = new ServiceBusMessage(new { id = input.Id, progress = "going", code = code }.ToJsonString());
+                    message.ApplicationProperties.Add("name", "Exam");
+                    if (records.Count > 0)
+                    {
+                        await _serviceBus.GetServiceBusClient().cancelMessage("active-task", records[0].sequenceNumber);
+                        long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", message, DateTimeOffset.FromUnixTimeMilliseconds(stime));
+                        records[0].sequenceNumber = start;
+                        await _azureStorage.SaveOrUpdate<ChangeRecord>(records[0]);
+                        //await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(record, record.id, new Azure.Cosmos.PartitionKey($"{record.code}"));
+                    }
+                    else
+                    {
+                        long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", message, DateTimeOffset.FromUnixTimeMilliseconds(stime));
+                        ChangeRecord changeRecord = new ChangeRecord
+                        {
+                            RowKey = input.Id,
+                            PartitionKey = "pending",
+                            sequenceNumber = start,
+                            msgId = message.MessageId
+                        };
+                        await _azureStorage.Save<ChangeRecord>(changeRecord);
+                        //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}"));
+                    }
+                    break;
+                case "going":
+                    if (examClassResults.Count == 0)
+                    {
+                        foreach (string cla in info.targetClassIds)
+                        {
+                            int m = 0;
+                            foreach (ExamSubject subject in info.subjects)
+                            {
+                                ExamClassResult result = new ExamClassResult
+                                {
+                                    code = "ExamClassResult-" + info.school,
+                                    examId = info.id,
+                                    id = Guid.NewGuid().ToString(),
+                                    subjectId = subject.id,
+                                    year = info.year,
+                                    scope = info.scope
+                                };
+                                result.info.id = cla;
+                                var sresponse = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(cla, new Azure.Cosmos.PartitionKey($"Class-{info.school}"));
+                                if (sresponse.Status == 200)
+                                {
+                                    using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
+                                    Class classroom = json.ToObject<Class>();
+                                    result.info.name = classroom.name;
+                                    List<string> ans = new List<string>();
+                                    List<double> ansPoint = new List<double>();
+                                    foreach (double p in info.papers[m].point)
+                                    {
+                                        //ans.Add(new List<string>());
+                                        ansPoint.Add(-1);
+                                    }
+                                    foreach (StudentSimple stu in classroom.students)
+                                    {
+                                        result.studentIds.Add(stu.id);
+                                        result.studentAnswers.Add(ans);
+                                        result.studentScores.Add(ansPoint);
+                                        result.sum.Add(0);
+                                    }
+                                }
+                                //result.progress = info.progress;
+                                result.school = info.school;
+                                m++;
+                                await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(result, new Azure.Cosmos.PartitionKey($"{result.code}"));
+                            }
+                        }
+                        // 发送信息通知
+                        var messageEnd = new ServiceBusMessage(new { id = input.Id, progress = "finish", code = code }.ToJsonString());
+                        messageEnd.ApplicationProperties.Add("name", "Exam");
+                        if (records.Count > 0)
+                        {
+                            long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
+                            await _serviceBus.GetServiceBusClient().cancelMessage("active-task", records[0].sequenceNumber);
+                            records[0].sequenceNumber = end;
+                            await _azureStorage.SaveOrUpdate<ChangeRecord>(records[0]);
+                            //await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(record, record.id, new Azure.Cosmos.PartitionKey($"{record.code}"));
+                        }
+                        else
+                        {
+                            long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
+                            ChangeRecord changeRecord = new ChangeRecord
+                            {
+                                RowKey = input.Id,
+                                PartitionKey = "going",
+                                sequenceNumber = end,
+                                msgId = messageEnd.MessageId
+                            };
+                            await _azureStorage.Save<ChangeRecord>(changeRecord);
+                            //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}"));
+                        }
+                    }
+                    else
+                    {
+                        //处理单科结算时科目与试卷信息匹配的问题
+                        int gno = 0;
+                        foreach (ExamSubject subject in info.subjects)
+                        {
+                            if (subject.classCount == info.targetClassIds.Count)
+                            {
+                                await createClassResultAsync(info, examClassResults, subject, gno,_azureCosmos);
+                            }
+                            gno++;
+                        }
+                    }
+                    break;
+                case "finish":
+                    int fno = 0;
+                    foreach (ExamSubject subject in info.subjects)
+                    {
+                        await createClassResultAsync(info, examClassResults, subject, fno, _azureCosmos);
+                        fno++;
+                    }
+
+                    break;
+            }
+        }
+        public static async Task createClassResultAsync(ExamInfo info, List<ExamClassResult> examClassResults, ExamSubject subject, int no, AzureCosmosFactory _azureCosmos)
+        {
+            //保证试卷信息与科目信息同步
+            ExamResult result = new ExamResult();
+            //人数总和
+            int Count = 0;
+            int m = 0;
+            List<ClassRange> classRanges = new List<ClassRange>();
+            foreach (ExamClassResult classResult in examClassResults)
+            {
+                if (classResult.subjectId.Equals(subject.id))
+                {
+                    foreach (List<double> scores in classResult.studentScores)
+                    {
+                        result.studentScores.Add(scores);
+                    }
+                    //处理班级信息
+                    ClassRange range = new ClassRange();
+                    range.id = classResult.info.id;
+                    range.name = classResult.info.name;
+                    List<int> ran = new List<int>();
+                    int stuCount = classResult.studentIds.Count;
+                    Count += stuCount;
+                    if (m == 0)
+                    {
+                        ran.Add(0);
+                        ran.Add(stuCount - 1);
+                    }
+                    else
+                    {
+                        ran.Add(Count - stuCount);
+                        ran.Add(Count - 1);
+                    }
+                    m++;
+                    range.range = ran;
+                    classRanges.Add(range);
+                    //处理学生ID 
+                    foreach (string id in classResult.studentIds)
+                    {
+                        result.studentIds.Add(id);
+                    }
+                }
+            }
+            result.classes = classRanges;
+            result.code = "ExamResult-" + info.id;
+            result.school = info.school;
+            result.id = subject.id;
+            result.examId = info.id;
+            result.subjectId = subject.id;
+            result.year = info.year;
+            result.paper = info.papers[no];
+            //result.point = info.papers[j].point;
+            result.scope = info.scope;
+            result.name = info.name;
+            result.time = info.startTime;
+            await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Common").UpsertItemAsync(result, new Azure.Cosmos.PartitionKey($"ExamResult-{info.id}"));
+
+        }
+    }
+}

+ 4 - 303
TEAMModelFunction/MonitorCosmosDB.cs

@@ -60,256 +60,13 @@ namespace TEAMModelFunction
                         switch (pk)
                         {
                             case "Exam":
-                                ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(input.Id, new Azure.Cosmos.PartitionKey($"{code}"));
-                                List<ExamClassResult> examClassResults = new List<ExamClassResult>();
-                                List<ExamSubject> examSubjects = new List<ExamSubject>();
-                                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select value(c) from c where c.examId = '{info.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"ExamClassResult-{school}") }))
-                                {
-                                    using var json = await JsonDocument.ParseAsync(item.ContentStream);
-                                    if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
-                                    {
-                                        foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
-                                        {
-                                            examClassResults.Add(obj.ToObject<ExamClassResult>());
-                                        }
-                                    }
-                                }
-
-                                List<ChangeRecord> records = await _azureStorage.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", input.Id }, { "PartitionKey", info.progress } });
-                                //ChangeRecord record = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ChangeRecord>(input.Id, new Azure.Cosmos.PartitionKey($"{info.progress}"));
-                                switch (info.progress)
-                                {
-                                    case "pending":
-                                        var message = new ServiceBusMessage(new { id = input.Id, progress = "going", code = code }.ToJsonString());
-                                        message.ApplicationProperties.Add("name", "Exam");
-                                        if (records.Count > 0)
-                                        {
-                                            await _serviceBus.GetServiceBusClient().cancelMessage("active-task", records[0].sequenceNumber);
-                                            long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", message, DateTimeOffset.FromUnixTimeMilliseconds(stime));
-                                            records[0].sequenceNumber = start;
-                                            await _azureStorage.SaveOrUpdate<ChangeRecord>(records[0]);
-                                            //await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(record, record.id, new Azure.Cosmos.PartitionKey($"{record.code}"));
-                                        }
-                                        else
-                                        {
-                                            long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", message, DateTimeOffset.FromUnixTimeMilliseconds(stime));
-                                            ChangeRecord changeRecord = new ChangeRecord
-                                            {
-                                                RowKey = input.Id,
-                                                PartitionKey = "pending",
-                                                sequenceNumber = start,
-                                                msgId = message.MessageId
-                                            };
-                                            await _azureStorage.Save<ChangeRecord>(changeRecord);
-                                            //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}"));
-                                        }
-                                        break;
-                                    case "going":
-                                        if (examClassResults.Count == 0)
-                                        {
-                                            foreach (string cla in info.targetClassIds) {
-                                                int m = 0;
-                                                foreach (ExamSubject subject in info.subjects) {
-                                                    ExamClassResult result = new ExamClassResult
-                                                    {
-                                                        code = "ExamClassResult-" + info.school,
-                                                        examId = info.id,
-                                                        id = Guid.NewGuid().ToString(),
-                                                        subjectId = subject.id,
-                                                        year = info.year,
-                                                        scope = info.scope
-                                                    };
-                                                    result.info.id = cla;
-                                                    var sresponse = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(cla, new Azure.Cosmos.PartitionKey($"Class-{info.school}"));
-                                                    if (sresponse.Status == 200)
-                                                    {
-                                                        using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
-                                                        Class classroom = json.ToObject<Class>();
-                                                        result.info.name = classroom.name;
-                                                        List<string> ans = new List<string>();
-                                                        List<double> ansPoint = new List<double>();
-                                                        foreach (double p in info.papers[m].point)
-                                                        {
-                                                            //ans.Add(new List<string>());
-                                                            ansPoint.Add(-1);
-                                                        }
-                                                        foreach (StudentSimple stu in classroom.students)
-                                                        {
-                                                            result.studentIds.Add(stu.id);
-                                                            result.studentAnswers.Add(ans);
-                                                            result.studentScores.Add(ansPoint);
-                                                            result.sum.Add(0);
-                                                        }
-                                                    }
-                                                    //result.progress = info.progress;
-                                                    result.school = info.school;
-                                                    m++;
-                                                    await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(result, new Azure.Cosmos.PartitionKey($"{result.code}"));
-                                                }
-                                            }
-                                            // 发送信息通知
-                                            var messageEnd = new ServiceBusMessage(new { id = input.Id, progress = "finish", code = code }.ToJsonString());
-                                            messageEnd.ApplicationProperties.Add("name", "Exam");
-                                            if (records.Count > 0)
-                                            {
-                                                long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
-                                                await _serviceBus.GetServiceBusClient().cancelMessage("active-task", records[0].sequenceNumber);
-                                                records[0].sequenceNumber = end;
-                                                await _azureStorage.SaveOrUpdate<ChangeRecord>(records[0]);
-                                                //await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(record, record.id, new Azure.Cosmos.PartitionKey($"{record.code}"));
-                                            }
-                                            else
-                                            {
-                                                long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
-                                                ChangeRecord changeRecord = new ChangeRecord
-                                                {
-                                                    RowKey = input.Id,
-                                                    PartitionKey = "going",
-                                                    sequenceNumber = end,
-                                                    msgId = messageEnd.MessageId
-                                                };
-                                                await _azureStorage.Save<ChangeRecord>(changeRecord);
-                                                //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}"));
-                                            }
-                                        }
-                                        else
-                                        {
-                                            //处理单科结算时科目与试卷信息匹配的问题
-                                            int gno = 0;
-                                            foreach (ExamSubject subject in info.subjects) {
-                                                if (subject.classCount == info.targetClassIds.Count) {
-                                                    await createClassResultAsync(info, examClassResults, subject, gno);
-                                                }
-                                                gno++;
-                                            }                                           
-                                        }
-                                        break;
-                                    case "finish":
-                                        int fno = 0;
-                                        foreach (ExamSubject subject in info.subjects) {
-                                            await createClassResultAsync(info, examClassResults, subject, fno);
-                                            fno++;
-                                        }
-                                       
-                                        break;
-                                }
+                                ExamTrigger.Trigger(_azureCosmos, _serviceBus, _azureStorage, _dingDing, client,input,code,stime,etime,school);
                                 break;
                             case "Vote":
-                                Vote vote = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<Vote>(input.Id, new Azure.Cosmos.PartitionKey($"{code}"));
-                                List<ChangeRecord> voteRecords = await _azureStorage.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", input.Id }, { "PartitionKey", vote.progress } });
-                                //ChangeRecord voteRecord = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ChangeRecord>(input.Id, new Azure.Cosmos.PartitionKey($"{vote.progress}"));
-                                switch (vote.progress)
-                                {
-                                    case "pending":
-                                        var messageVote = new ServiceBusMessage(new { id = input.Id, progress = "going", code = code }.ToJsonString());
-                                        messageVote.ApplicationProperties.Add("name", "Vote");
-                                        if (voteRecords.Count > 0)
-                                        {
-                                            long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageVote, DateTimeOffset.FromUnixTimeMilliseconds(stime));
-                                            await _serviceBus.GetServiceBusClient().cancelMessage("active-task", voteRecords[0].sequenceNumber);
-                                            voteRecords[0].sequenceNumber = start;
-                                            await _azureStorage.SaveOrUpdate<ChangeRecord>(voteRecords[0]);
-                                            //await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(voteRecord, voteRecord.id, new Azure.Cosmos.PartitionKey($"{voteRecord.code}"));
-                                        }
-                                        else
-                                        {
-                                            long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageVote, DateTimeOffset.FromUnixTimeMilliseconds(stime));
-                                            ChangeRecord changeRecord = new ChangeRecord
-                                            {
-                                                RowKey = input.Id,
-                                                PartitionKey = "pending",
-                                                sequenceNumber = start,
-                                                msgId = messageVote.MessageId
-                                            };
-                                            await _azureStorage.Save<ChangeRecord>(changeRecord);
-                                            //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}"));
-                                        }
-                                        break;
-                                    case "going":
-                                        var messageVoteEnd = new ServiceBusMessage(new { id = input.Id, progress = "finish", code = code }.ToJsonString());
-                                        messageVoteEnd.ApplicationProperties.Add("name", "Vote");
-                                        if (voteRecords.Count > 0)
-                                        {
-                                            long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageVoteEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
-                                            await _serviceBus.GetServiceBusClient().cancelMessage("active-task", voteRecords[0].sequenceNumber);
-                                            voteRecords[0].sequenceNumber = end;
-                                            await _azureStorage.SaveOrUpdate<ChangeRecord>(voteRecords[0]);
-                                            //await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(voteRecord, voteRecord.id, new Azure.Cosmos.PartitionKey($"{voteRecord.code}"));
-                                        }
-                                        else
-                                        {
-                                            long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageVoteEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
-                                            ChangeRecord changeRecord = new ChangeRecord
-                                            {
-                                                RowKey = input.Id,
-                                                PartitionKey = "going",
-                                                sequenceNumber = end,
-                                                msgId = messageVoteEnd.MessageId
-                                            };
-                                            await _azureStorage.Save<ChangeRecord>(changeRecord);
-                                            //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}"));
-                                        }
-                                        break;
-                                }
+                                VoteTrigger.Trigger(_azureCosmos, _serviceBus, _azureStorage, _dingDing, client, input, code, stime, etime, school);
                                 break;
                             case "Survey":
-                                Survey survey = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<Survey>(input.Id, new Azure.Cosmos.PartitionKey($"{code}"));
-                                //messageSurvey.ScheduledEnqueueTime = DateTimeOffset.FromUnixTimeMilliseconds(stime);
-                                //string msgid = messageSurvey.MessageId;
-                                List<ChangeRecord> changeRecords = await _azureStorage.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", input.Id }, { "PartitionKey", survey.progress } });
-                                //ChangeRecord surveyRecord = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ChangeRecord>(input.Id, new Azure.Cosmos.PartitionKey($"{survey.progress}"));
-                                switch (survey.progress)
-                                {
-                                    case "pending":
-                                        var messageSurvey = new ServiceBusMessage(new { id = input.Id, progress = "going", code = code }.ToJsonString());
-                                        messageSurvey.ApplicationProperties.Add("name", "Survey");
-                                        if (changeRecords.Count > 0)
-                                        {
-                                            await _serviceBus.GetServiceBusClient().cancelMessage("active-task", changeRecords[0].sequenceNumber);
-                                            long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageSurvey, DateTimeOffset.FromUnixTimeMilliseconds(stime));
-                                            changeRecords[0].sequenceNumber = start;
-                                            await _azureStorage.SaveOrUpdate<ChangeRecord>(changeRecords[0]);
-                                            //await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(surveyRecord, surveyRecord.id, new Azure.Cosmos.PartitionKey($"{surveyRecord.code}"));
-                                        }
-                                        else
-                                        {
-                                            long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageSurvey, DateTimeOffset.FromUnixTimeMilliseconds(stime));
-                                            ChangeRecord changeRecord = new ChangeRecord
-                                            {
-                                                RowKey = input.Id,
-                                                PartitionKey = "pending",
-                                                sequenceNumber = start,
-                                                msgId = messageSurvey.MessageId
-                                            };
-                                            await _azureStorage.Save<ChangeRecord>(changeRecord);
-                                            //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}"));
-                                        }
-                                        break;
-                                    case "going":
-                                        var messageSurveyEnd = new ServiceBusMessage(new { id = input.Id, progress = "finish", code = code }.ToJsonString());
-                                        messageSurveyEnd.ApplicationProperties.Add("name", "Survey");
-                                        if (changeRecords.Count > 0)
-                                        {
-                                            long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageSurveyEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
-                                            await _serviceBus.GetServiceBusClient().cancelMessage("active-task", changeRecords[0].sequenceNumber);
-                                            changeRecords[0].sequenceNumber = end;
-                                            await _azureStorage.SaveOrUpdate<ChangeRecord>(changeRecords[0]);
-                                        }
-                                        else
-                                        {
-                                            long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageSurveyEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
-                                            ChangeRecord changeRecord = new ChangeRecord
-                                            {
-                                                RowKey = input.Id,
-                                                PartitionKey = "going",
-                                                sequenceNumber = end,
-                                                msgId = messageSurveyEnd.MessageId
-                                            };
-                                            await _azureStorage.Save<ChangeRecord>(changeRecord);
-                                            //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}"));
-                                        }
-                                        break;
-                                }
+                                SurveyTrigger.Trigger(_azureCosmos, _serviceBus, _azureStorage, _dingDing, client, input, code, stime, etime, school);
                                 break;
 
                         }
@@ -317,62 +74,6 @@ namespace TEAMModelFunction
                 }
             }
         }
-        public async Task createClassResultAsync(ExamInfo info,List<ExamClassResult> examClassResults,ExamSubject subject,int no) {
-            //保证试卷信息与科目信息同步
-                ExamResult result = new ExamResult();
-                //人数总和
-                int Count = 0;
-                int m = 0;
-                List<ClassRange> classRanges = new List<ClassRange>();
-                foreach (ExamClassResult classResult in examClassResults)
-                {
-                    if (classResult.subjectId.Equals(subject.id))
-                    {
-                        foreach (List<double> scores in classResult.studentScores)
-                        {
-                            result.studentScores.Add(scores);
-                        }
-                        //处理班级信息
-                        ClassRange range = new ClassRange();
-                        range.id = classResult.info.id;
-                        range.name = classResult.info.name;
-                        List<int> ran = new List<int>();
-                        int stuCount = classResult.studentIds.Count;
-                        Count += stuCount;
-                        if (m == 0)
-                        {
-                            ran.Add(0);
-                            ran.Add(stuCount - 1);
-                        }
-                        else
-                        {
-                            ran.Add(Count - stuCount);
-                            ran.Add(Count - 1);
-                        }
-                        m++;
-                        range.range = ran;
-                        classRanges.Add(range);
-                        //处理学生ID 
-                        foreach (string id in classResult.studentIds)
-                        {
-                            result.studentIds.Add(id);
-                        }
-                    }
-                }
-                result.classes = classRanges;
-                result.code = "ExamResult-" + info.id;
-                result.school = info.school;
-                result.id = subject.id;
-                result.examId = info.id;
-                result.subjectId = subject.id;
-                result.year = info.year;
-                result.paper = info.papers[no];
-                //result.point = info.papers[j].point;
-                result.scope = info.scope;
-                result.name = info.name;
-                result.time = info.startTime;
-                await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Common").UpsertItemAsync(result, new Azure.Cosmos.PartitionKey($"ExamResult-{info.id}"));
-            
-        }
+        
     }
 }

+ 79 - 0
TEAMModelFunction/SurveyTrigger.cs

@@ -0,0 +1,79 @@
+using Azure.Cosmos;
+using Azure.Messaging.ServiceBus;
+using Microsoft.Azure.Documents;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Models;
+
+namespace TEAMModelFunction
+{
+   public class SurveyTrigger
+    {
+        public static async void Trigger(AzureCosmosFactory _azureCosmos, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, DingDing _dingDing,
+               CosmosClient client, Document input, string code, long stime, long etime, string school)
+        {
+            Survey survey = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<Survey>(input.Id, new Azure.Cosmos.PartitionKey($"{code}"));
+            //messageSurvey.ScheduledEnqueueTime = DateTimeOffset.FromUnixTimeMilliseconds(stime);
+            //string msgid = messageSurvey.MessageId;
+            List<ChangeRecord> changeRecords = await _azureStorage.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", input.Id }, { "PartitionKey", survey.progress } });
+            //ChangeRecord surveyRecord = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ChangeRecord>(input.Id, new Azure.Cosmos.PartitionKey($"{survey.progress}"));
+            switch (survey.progress)
+            {
+                case "pending":
+                    var messageSurvey = new ServiceBusMessage(new { id = input.Id, progress = "going", code = code }.ToJsonString());
+                    messageSurvey.ApplicationProperties.Add("name", "Survey");
+                    if (changeRecords.Count > 0)
+                    {
+                        await _serviceBus.GetServiceBusClient().cancelMessage("active-task", changeRecords[0].sequenceNumber);
+                        long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageSurvey, DateTimeOffset.FromUnixTimeMilliseconds(stime));
+                        changeRecords[0].sequenceNumber = start;
+                        await _azureStorage.SaveOrUpdate<ChangeRecord>(changeRecords[0]);
+                        //await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(surveyRecord, surveyRecord.id, new Azure.Cosmos.PartitionKey($"{surveyRecord.code}"));
+                    }
+                    else
+                    {
+                        long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageSurvey, DateTimeOffset.FromUnixTimeMilliseconds(stime));
+                        ChangeRecord changeRecord = new ChangeRecord
+                        {
+                            RowKey = input.Id,
+                            PartitionKey = "pending",
+                            sequenceNumber = start,
+                            msgId = messageSurvey.MessageId
+                        };
+                        await _azureStorage.Save<ChangeRecord>(changeRecord);
+                        //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}"));
+                    }
+                    break;
+                case "going":
+                    var messageSurveyEnd = new ServiceBusMessage(new { id = input.Id, progress = "finish", code = code }.ToJsonString());
+                    messageSurveyEnd.ApplicationProperties.Add("name", "Survey");
+                    if (changeRecords.Count > 0)
+                    {
+                        long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageSurveyEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
+                        await _serviceBus.GetServiceBusClient().cancelMessage("active-task", changeRecords[0].sequenceNumber);
+                        changeRecords[0].sequenceNumber = end;
+                        await _azureStorage.SaveOrUpdate<ChangeRecord>(changeRecords[0]);
+                    }
+                    else
+                    {
+                        long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageSurveyEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
+                        ChangeRecord changeRecord = new ChangeRecord
+                        {
+                            RowKey = input.Id,
+                            PartitionKey = "going",
+                            sequenceNumber = end,
+                            msgId = messageSurveyEnd.MessageId
+                        };
+                        await _azureStorage.Save<ChangeRecord>(changeRecord);
+                        //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}"));
+                    }
+                    break;
+            }
+        }
+    }
+}

+ 79 - 0
TEAMModelFunction/VoteTrigger.cs

@@ -0,0 +1,79 @@
+using Azure.Cosmos;
+using Azure.Messaging.ServiceBus;
+using Microsoft.Azure.Documents;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Models;
+
+namespace TEAMModelFunction
+{
+  public static  class VoteTrigger
+    {
+
+        public static async void Trigger(AzureCosmosFactory _azureCosmos, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, DingDing _dingDing,
+            CosmosClient client, Document input, string code, long stime, long etime, string school)
+        {
+            Vote vote = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<Vote>(input.Id, new Azure.Cosmos.PartitionKey($"{code}"));
+            List<ChangeRecord> voteRecords = await _azureStorage.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", input.Id }, { "PartitionKey", vote.progress } });
+            //ChangeRecord voteRecord = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ChangeRecord>(input.Id, new Azure.Cosmos.PartitionKey($"{vote.progress}"));
+            switch (vote.progress)
+            {
+                case "pending":
+                    var messageVote = new ServiceBusMessage(new { id = input.Id, progress = "going", code = code }.ToJsonString());
+                    messageVote.ApplicationProperties.Add("name", "Vote");
+                    if (voteRecords.Count > 0)
+                    {
+                        long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageVote, DateTimeOffset.FromUnixTimeMilliseconds(stime));
+                        await _serviceBus.GetServiceBusClient().cancelMessage("active-task", voteRecords[0].sequenceNumber);
+                        voteRecords[0].sequenceNumber = start;
+                        await _azureStorage.SaveOrUpdate<ChangeRecord>(voteRecords[0]);
+                        //await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(voteRecord, voteRecord.id, new Azure.Cosmos.PartitionKey($"{voteRecord.code}"));
+                    }
+                    else
+                    {
+                        long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageVote, DateTimeOffset.FromUnixTimeMilliseconds(stime));
+                        ChangeRecord changeRecord = new ChangeRecord
+                        {
+                            RowKey = input.Id,
+                            PartitionKey = "pending",
+                            sequenceNumber = start,
+                            msgId = messageVote.MessageId
+                        };
+                        await _azureStorage.Save<ChangeRecord>(changeRecord);
+                        //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}"));
+                    }
+                    break;
+                case "going":
+                    var messageVoteEnd = new ServiceBusMessage(new { id = input.Id, progress = "finish", code = code }.ToJsonString());
+                    messageVoteEnd.ApplicationProperties.Add("name", "Vote");
+                    if (voteRecords.Count > 0)
+                    {
+                        long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageVoteEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
+                        await _serviceBus.GetServiceBusClient().cancelMessage("active-task", voteRecords[0].sequenceNumber);
+                        voteRecords[0].sequenceNumber = end;
+                        await _azureStorage.SaveOrUpdate<ChangeRecord>(voteRecords[0]);
+                        //await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(voteRecord, voteRecord.id, new Azure.Cosmos.PartitionKey($"{voteRecord.code}"));
+                    }
+                    else
+                    {
+                        long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageVoteEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
+                        ChangeRecord changeRecord = new ChangeRecord
+                        {
+                            RowKey = input.Id,
+                            PartitionKey = "going",
+                            sequenceNumber = end,
+                            msgId = messageVoteEnd.MessageId
+                        };
+                        await _azureStorage.Save<ChangeRecord>(changeRecord);
+                        //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}"));
+                    }
+                    break;
+            }
+        }
+    }
+}

+ 20 - 18
TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactory.cs

@@ -35,7 +35,7 @@ namespace TEAMModelOS.SDK.DI
         }
 
         public BlobServiceClient GetBlobServiceClient(string name = "Default")
-        {            
+        {
             try
             {
                 var options = _optionsMonitor.Get(name);
@@ -50,7 +50,7 @@ namespace TEAMModelOS.SDK.DI
         }
 
         public BlobContainerClient GetBlobContainerClient(string containerName, string name = "Default")
-        {            
+        {
             try
             {
                 var options = _optionsMonitor.Get(name);
@@ -62,9 +62,9 @@ namespace TEAMModelOS.SDK.DI
                 return null;
             }
         }
-        
+
         public BlobBatchClient GetBlobBatchClient(string name = "Default")
-        {           
+        {
             try
             {
                 var options = _optionsMonitor.Get(name);
@@ -85,7 +85,7 @@ namespace TEAMModelOS.SDK.DI
         /// <param name="blobContainerSasPermissions">權限(可多選)Flags</param>
         /// <param name="name"></param>
         /// <returns></returns>
-        public (string uri ,string sas) GetBlobContainerSAS(string containerName, BlobContainerSasPermissions blobContainerSasPermissions, string name = "Default")
+        public (string uri, string sas) GetBlobContainerSAS(string containerName, BlobContainerSasPermissions blobContainerSasPermissions, string name = "Default")
         {
             try
             {
@@ -154,11 +154,13 @@ namespace TEAMModelOS.SDK.DI
                     BlobContainerName = containerName
                 };
                 BlobContainerSasPermissions blobContainerSasPermissions = BlobContainerSasPermissions.Read;
-                if (isRead) {
+                if (isRead)
+                {
                     blobContainerSasPermissions = BlobContainerSasPermissions.Read;
                 }
-                else {
-                    blobContainerSasPermissions = BlobContainerSasPermissions.Delete| BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Create | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List;
+                else
+                {
+                    blobContainerSasPermissions = BlobContainerSasPermissions.Delete | BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Create | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List;
                 }
                 blobSasBuilder.SetPermissions(blobContainerSasPermissions);
                 var sskc = new StorageSharedKeyCredential(accountname, accountkey);
@@ -170,12 +172,12 @@ namespace TEAMModelOS.SDK.DI
                     Path = containerName
                     //Query = sasQueryParameters.ToString()
                 };
-                return new BlobAuth { url = fullUri.Uri.ToString().Replace(fullUri.Uri.LocalPath,""), sas = sasQueryParameters.ToString(), timeout = time, name = containerName };
-               // return (fullUri.Uri.ToString(), sasQueryParameters.ToString());
+                return new BlobAuth { url = fullUri.Uri.ToString().Replace(fullUri.Uri.LocalPath, ""), sas = sasQueryParameters.ToString(), timeout = time, name = containerName };
+                // return (fullUri.Uri.ToString(), sasQueryParameters.ToString());
             }
             catch
             {
-                return   null ;
+                return null;
             }
         }
 
@@ -232,7 +234,7 @@ namespace TEAMModelOS.SDK.DI
         /// <param name="blobSasPermissions"></param>
         /// <param name="name"></param>
         /// <returns></returns>
-        public BlobAuth GetBlobSasUriRead(string containerName, string blobName,string name = "Default")
+        public BlobAuth GetBlobSasUriRead(string containerName, string blobName, string name = "Default")
         {
             try
             {
@@ -240,7 +242,7 @@ namespace TEAMModelOS.SDK.DI
                 var accountname = keys["AccountName"];
                 var accountkey = keys["AccountKey"];
                 var endpoint = keys["EndpointSuffix"];
-                DateTimeOffset dateTime = DateTimeOffset.UtcNow.Add(new TimeSpan(365*99, 0, 15, 0));
+                DateTimeOffset dateTime = DateTimeOffset.UtcNow.Add(new TimeSpan(365 * 99, 0, 15, 0));
                 long time = dateTime.ToUnixTimeMilliseconds();
                 var blobSasBuilder = new BlobSasBuilder
                 {
@@ -261,7 +263,7 @@ namespace TEAMModelOS.SDK.DI
                     Query = sasQueryParameters.ToString()
                 };
                 return new BlobAuth { url = fullUri.Uri.ToString(), sas = sasQueryParameters.ToString(), timeout = time };
-               // return fullUri.Uri.ToString();
+                // return fullUri.Uri.ToString();
             }
             catch
             {
@@ -270,7 +272,7 @@ namespace TEAMModelOS.SDK.DI
         }
 
         public CloudTableClient GetCloudTableClient(string name = "Default")
-        {            
+        {
             try
             {
                 var options = _optionsMonitor.Get(name);
@@ -284,7 +286,7 @@ namespace TEAMModelOS.SDK.DI
             }
         }
 
-       
+
 
         /// <summary>
         /// 可讓您管理儲存體帳戶中的所有佇列
@@ -292,7 +294,7 @@ namespace TEAMModelOS.SDK.DI
         /// <param name="name"></param>
         /// <returns></returns>
         public QueueServiceClient GetQueueServiceClient(string name = "Default")
-        {            
+        {
             try
             {
                 var options = _optionsMonitor.Get(name);
@@ -325,7 +327,7 @@ namespace TEAMModelOS.SDK.DI
                 return null;
             }
         }
-        public  async Task<CloudTable> InitializeTable<T>()
+        public async Task<CloudTable> InitializeTable<T>()
         {
             string TableName = GetTableSpace<T>();
             CloudTable cloudTable = GetCloudTableClient().GetTableReference(TableName);

+ 5 - 0
TEAMModelOS.SDK/Extension/Utils.cs

@@ -75,6 +75,11 @@ namespace TEAMModelOS.SDK.Extension
             return value;
         }        
 
+        /// <summary>
+        /// 剖析連接字串
+        /// </summary>
+        /// <param name="connectionString"></param>
+        /// <returns></returns>
         public static Dictionary<string, string> ParseConnectionString(string connectionString)
         {
             var d = new Dictionary<string, string>();

+ 21 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/CommonData.cs

@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.Models.Cosmos.Student
+{
+    public class CommonData : CosmosEntity
+    {
+        public CommonData() {
+            pk = "Common";
+        }
+        /// <summary>
+        /// 业务类型  vote投票 survey问卷 exam评测 learn学习活动 homework作业活动
+        /// </summary>
+        public string type { get; set; }
+        public string name { get; set; }
+        public string startTime { get; set; }
+        public string endTime { get; set; }
+        public string scode { get; set; }
+    }
+}

+ 22 - 21
TEAMModelOS.SDK/Models/Cosmos/School/Vote.cs

@@ -12,14 +12,14 @@ namespace TEAMModelOS.SDK.Models
     /// 投票
     /// </summary>    
     public class Vote : CosmosEntity
-    {   
+    {
         public Vote()
         {
             pk = "Vote";
             options = new List<OptionsVote>();
 
         }
-        
+
         /// <summary>
         /// 投票名称
         /// </summary>
@@ -57,12 +57,12 @@ namespace TEAMModelOS.SDK.Models
         public string description { get; set; }
 
 
-/*        /// <summary>
-        /// 投票附件
-        /// </summary>
-        [ProtoMember(9)]
-        public List<ProcessRes> resource { get; set; }
-*/
+        /*        /// <summary>
+                /// 投票附件
+                /// </summary>
+                [ProtoMember(9)]
+                public List<ProcessRes> resource { get; set; }
+        */
 
         /// <summary>
         /// 状态 (100:待发布 200:已发布 300:已结束)
@@ -70,24 +70,25 @@ namespace TEAMModelOS.SDK.Models
         public int status { get; set; }
 
 
-/*        /// <summary>
-        /// 模式
-        /// </summary>
-        [ProtoMember(11)]
-        public List<string> other { get; set; }*/
+        /*        /// <summary>
+                /// 模式
+                /// </summary>
+                [ProtoMember(11)]
+                public List<string> other { get; set; }*/
 
-/*
-        public string url { get; set; }
+        /*
+                public string url { get; set; }
 
-        /// <summary>
-        /// 选项
-        /// </summary>
-        [ProtoMember(12)]
-        public List<Option> option { get; set; }*/
+                /// <summary>
+                /// 选项
+                /// </summary>
+                [ProtoMember(12)]
+                public List<Option> option { get; set; }*/
 
         //public long sequenceNumber { get; set; }
     }
-    public class OptionsVote { 
+    public class OptionsVote
+    {
         public string code { get; set; }
         public string value { get; set; }
         public string desc { get; set; }

+ 46 - 0
TEAMModelOS/ClientApp/src/assets/iconfont/demo_index.html

@@ -30,6 +30,18 @@
       <div class="content unicode" style="display: block;">
           <ul class="icon_lists dib-box">
           
+            <li class="dib">
+              <span class="icon iconfont">&#xe640;</span>
+                <div class="name">半对</div>
+                <div class="code-name">&amp;#xe640;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe99d;</span>
+                <div class="name">完成</div>
+                <div class="code-name">&amp;#xe99d;</div>
+              </li>
+          
             <li class="dib">
               <span class="icon iconfont">&#xe63f;</span>
                 <div class="name">表格</div>
@@ -452,6 +464,24 @@
       <div class="content font-class">
         <ul class="icon_lists dib-box">
           
+          <li class="dib">
+            <span class="icon iconfont icon-half-right"></span>
+            <div class="name">
+              半对
+            </div>
+            <div class="code-name">.icon-half-right
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-complete"></span>
+            <div class="name">
+              完成
+            </div>
+            <div class="code-name">.icon-complete
+            </div>
+          </li>
+          
           <li class="dib">
             <span class="icon iconfont icon-table"></span>
             <div class="name">
@@ -1039,6 +1069,22 @@
       <div class="content symbol">
           <ul class="icon_lists dib-box">
           
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-half-right"></use>
+                </svg>
+                <div class="name">半对</div>
+                <div class="code-name">#icon-half-right</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-complete"></use>
+                </svg>
+                <div class="name">完成</div>
+                <div class="code-name">#icon-complete</div>
+            </li>
+          
             <li class="dib">
                 <svg class="icon svg-icon" aria-hidden="true">
                   <use xlink:href="#icon-table"></use>

File diff suppressed because it is too large
+ 14 - 6
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.css


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


File diff suppressed because it is too large
+ 1 - 1
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.js


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

@@ -5,6 +5,20 @@
   "css_prefix_text": "icon-",
   "description": "",
   "glyphs": [
+    {
+      "icon_id": "5831259",
+      "name": "半对",
+      "font_class": "half-right",
+      "unicode": "e640",
+      "unicode_decimal": 58944
+    },
+    {
+      "icon_id": "7674533",
+      "name": "完成",
+      "font_class": "complete",
+      "unicode": "e99d",
+      "unicode_decimal": 59805
+    },
     {
       "icon_id": "1305461",
       "name": "表格",

File diff suppressed because it is too large
+ 6 - 0
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.svg


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


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


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


+ 12 - 4
TEAMModelOS/ClientApp/src/common/BaseCanvas.vue

@@ -66,12 +66,20 @@ export default {
     },
 
     watch:{
-        options:{
-            handler(){
-                this.init();
+        'options.writeWidth':{
+            handler(n){
+				this.context.lineWidth = n
+				this.config.writeWidth = n
             },
             deep: true
-        }
+        },
+		'options.writeColor':{
+		    handler(n){
+				this.context.strokeStyle = n
+				this.config.writeColor = n
+		    },
+		    deep: true
+		}
     },
 
     methods: {

+ 2 - 0
TEAMModelOS/ClientApp/src/common/BaseMyCanvas.vue

@@ -84,6 +84,7 @@ export default {
 		},
 		
 		onSelectWriteColor(val){
+			console.log(val)
 			this.options.writeColor = val
 			this.activeColor = val
 		},
@@ -93,6 +94,7 @@ export default {
 		},
 		
 		onSelectWriteWidth(val){
+			console.log(val)
 			this.options.writeWidth = val
 			this.activeDot = val
 		},

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

@@ -11,7 +11,7 @@
 					</a>
 					<DropdownMenu slot="list" v-if="user.roles.length > 1">
 						<DropdownItem v-if="curRole != 'teacher' && curRole != 'admin'" :name="'teacher'">教师</DropdownItem>
-						<DropdownItem v-if="curRole != 'student' && user.roles.indexOf('student') >= 0" :name="'student'">學生</DropdownItem>
+						<DropdownItem v-if="curRole != 'student'" :name="'student'">學生</DropdownItem>
 					</DropdownMenu>
 				</Dropdown>
 			</div>

+ 6 - 14
TEAMModelOS/ClientApp/src/components/evaluation/ExerciseList.vue

@@ -38,17 +38,13 @@
 								<span class="explain-title">【答ㅤ案】</span>
 								<div class="item-explain-details">
 									<!-- 问答题答案 -->
-									<div v-if="item.type === 'subjective'">
+									<div v-if="item.type === 'subjective' || item.type === 'complete'">
 										<span v-for="(answer, index) in item.answer" :key="index" v-html="item.answer.length ? answer : '未设置答案'"></span>
 									</div>
 									<!-- 问答题答案 -->
 									<div v-else-if="item.type === 'judge'">
 										<span>{{ item.answer.length ? (item.answer[0] === 'A' ? '正确' : '错误') : '未设置答案' }}</span>
 									</div>
-									<!-- 填空题答案 -->
-									<div v-else-if="item.type === 'complete'">
-										<span :class="[ item.type === 'complete' ? 'item-answer-item' : '',]" v-for="(answer, index) in item.answer" :key="index" v-html="answer"></span>
-									</div>
 									<!-- 其余题型答案 -->
 									<div v-else>
 										<span :class="[ item.type === 'complete' ? 'item-answer-item' : '' ]" v-for="(answer, index) in item.answer" :key="index">{{ answer }}</span>
@@ -282,17 +278,13 @@
 			// console.log('拿到已选',this.selQue)
 			this.selectList = this.selQue
 			
-			this.$EventBus.$off('onPaperItemChange')
-			this.$EventBus.$on('onPaperItemChange', data => {
-				this.selectList = data
-			})
+			// this.$EventBus.$off('onPaperItemChange')
+			// this.$EventBus.$on('onPaperItemChange', data => {
+			// 	console.log('EventBus',data)
+			// 	this.selectList = data
+			// })
 		},
 		computed: {
-			headers() {
-				let hd = {};
-				hd["Authorization"] = "Bearer " + localStorage.getItem("token");
-				return hd;
-			},
 			curScope() {
 				return this.filterOrigin === this.$store.state.userInfo.schoolCode ?
 					"school" :

+ 16 - 0
TEAMModelOS/ClientApp/src/components/questionnaire/BaseQnForm.less

@@ -8,6 +8,22 @@
 
 .component-qn-form {
     padding: 20px 20px 50px 20px;
+	
+	.vote-class{
+		display: flex;
+		flex-wrap: wrap;
+		
+		&-item{
+			background-color: @primary-color;
+			color:@primary-textColor;
+			height: 28px;
+			line-height: 28px;
+			padding: 0 10px;
+			font-size: 12px;
+			border-radius: 2px;
+			margin: 10px 4px;
+		}
+	}
 
     .ivu-form .ivu-form-item-label {
         color: @second-textColor;

+ 34 - 8
TEAMModelOS/ClientApp/src/components/questionnaire/BaseQnForm.vue

@@ -6,14 +6,17 @@
 			</FormItem>
 
 			<FormItem label="问卷对象" prop="targetClassIds">
-				<Select multiple v-model="qnForm.targetClassIds" :class="!qnFormEdit ? 'qn-form-disabled':''" placeholder="请选择问卷发布对象">
+				<RadioGroup v-model="classType" @on-change="onClassTypeChange" v-if="qnFormEdit">
+				        <Radio label="private">个人班级</Radio>
+				        <Radio label="school">校本班级</Radio>
+				</RadioGroup>
+				<div v-if="!qnFormEdit && curQnItem" class="vote-class">
+					<span v-for="item in curQnItem.targetClassIds" class="vote-class-item">{{ getTargetName(item) }}</span>
+				</div>
+				<Select multiple v-model="qnForm.targetClassIds" :class="!qnFormEdit ? 'qn-form-disabled':''" placeholder="请选择问卷发布对象" v-else>
 					<!-- <Option v-for="(item,index) in classRooms" :value="item.id" :key="index">{{ item.name }}</Option> -->
-					<OptionGroup label="个人班级">
-						<Option v-for="item in classRooms.filter(i=>i.scope === 'private')" :value="item.id" :key="item.id">{{ item.name }}</Option>
-					</OptionGroup>
-					<OptionGroup label="校本班级">
-						<Option v-for="item in classRooms.filter(i=>i.scope === 'school')" :value="item.id" :key="item.id">{{ item.name }}</Option>
-					</OptionGroup>
+						<Option v-for="item in classRooms.filter(i=>i.scope === classType)" :value="item.id" :key="item.id">{{ item.name }}</Option>
+						<!-- <Option v-for="item in classRooms" :value="item.id" :key="item.id">{{ item.name }}</Option> -->
 				</Select>
 			</FormItem>
 
@@ -55,6 +58,8 @@
 		},
 		data() {
 			return {
+				curQnItem:null,
+				classType:'private',
 				isFalse: false,
 				isLoading: false,
 				isRelatedContent: false,
@@ -123,6 +128,9 @@
 			}
 		},
 		methods: {
+			onClassTypeChange(val){
+				this.qnForm.targetClassIds = []
+			},
 
 			onChangeRange(arr) {
 				if(arr[0] === ''){
@@ -251,9 +259,27 @@
 					rangeTime: item.endTime ? [item.startTime,item.endTime] : null
 				}
 				this.currentState = item.state
-
+				this.$nextTick(() => {
+					this.curQnItem = JSON.parse(JSON.stringify(item))
+					if(item.targetClassIds.length){
+						let isExist = this.classRooms.filter(i => i.id === item.targetClassIds[0])
+						this.classType = isExist ? isExist[0].scope : 'private'
+					}
+				})
 				this.descriptionEditor.txt.html(item.description)
 			},
+			
+			/* 根据班级ID获取班级名称 */
+			getTargetName(classId){
+				if(this.classRooms.length){
+					let targetIndex = this.classRooms.map(i => i.id).indexOf(classId)
+					return targetIndex > -1 ?  this.classRooms[targetIndex].name : '未匹配数据'
+				}else{
+					this.getClassrooms(this.userInfo.TEAMModelId).then(res => {
+						return res.filter(i => i.id === classId)[0].name
+					})
+				}
+			}
 
 		},
 		mounted() {

+ 1 - 8
TEAMModelOS/ClientApp/src/components/selflearn/ExerciseList.vue

@@ -117,16 +117,9 @@
                                 <span class="explain-title">【答ㅤ案】</span>
                                 <div class="item-explain-details">
                                     <!-- 问答题答案 -->
-                                    <div v-if="item.type === 'subjective'">
+                                    <div v-if="item.type === 'subjective' || item.type === 'complete'">
                                         <span v-for="(answer, index) in item.answer" :key="index" v-html="item.answer.length ? answer : '未设置答案'"></span>
                                     </div>
-                                    <!-- 填空题答案 -->
-                                    <div v-else-if="item.type === 'complete'">
-                                        <span :class="[
-                        item.type === 'complete' ? 'item-answer-item' : '',
-                      ]"
-                                              v-for="(answer, index) in item.answer" :key="index" v-html="answer"></span>
-                                    </div>
                                     <!-- 其余题型答案 -->
                                     <div v-else>
                                         <span :class="[

+ 2 - 2
TEAMModelOS/ClientApp/src/components/selflearn/NewChooseContent.vue

@@ -593,7 +593,7 @@
             getSchoolBaseInfo() {
                 this.$store.dispatch('user/getSchoolProfile').then(
                     res => {
-                        if (res) {
+                        if (res.school_base) {
                             if (res.school_base.period.length > 0) {
                                 this.syllabusFilter.periodCode = res.school_base.period[0].id
                                 this.subjectList = res.school_base.period[0].subjects
@@ -602,7 +602,7 @@
                                 }
                             }
                         } else {
-                            this.$Message.warning('尚未加入学校,没有学校相关信息')
+                            // this.$Message.warning('尚未加入学校,没有学校相关信息')
                         }
                     }
                 )

+ 3 - 3
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContent.vue

@@ -10,7 +10,7 @@
         <Homework/>
       </div>-->
       <div v-if="this.$store.getters.getItemTitle.eventType=='exam'">
-        <LessonTest/>
+        <PaperView/>
       </div>
       <!--<div v-if="this.$store.getters.getItemTitle.eventType=='投票'">
         <Vote/>
@@ -32,7 +32,7 @@ import mockdata from "@/api";
 import Homework from "./EventContentTypeTemplate/Homework";
 import PreviewMission from "./EventContentTypeTemplate/PreviewMission";
 import Vote from "./EventContentTypeTemplate/Vote";
-import LessonTest from "./EventContentTypeTemplate/LessonTest";
+import PaperView from "./EventContentTypeTemplate/PaperView";
 import VoteHint from "./EventContentTypeTemplate/VoteHint";
 import QuesNaire from "./EventContentTypeTemplate/QuesNaire";
 export default {
@@ -40,7 +40,7 @@ export default {
   components: {
     Homework,
     PreviewMission,
-    LessonTest,
+    PaperView,
     Vote,
     VoteHint,
     QuesNaire

+ 298 - 296
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReport.vue

@@ -41,7 +41,7 @@
                                 </div>
                             </Card>
                         </i-col>
-                        <i-col :xs="24" :sm="24" :md="24" :lg="24">
+                        <i-col :xs="24" :sm="24" :md="24" :lg="24" style="display:none">
                             <Card class="comment-card">
                                 <p class="card-title">{{$t('studentWeb.exam.smartComment')}}</p>
                                 <div class="card-comment">
@@ -132,14 +132,14 @@
                         }
                     }
                     if (k != 0) {
-                        let index = 0
-                        for (let items of this.examInfo.stuAns) {
-                            if (items.length == 0) {
-                                index++
-                            }
-                        }
-                        if (index !== 0) {
-                            this.testState = index == this.examInfo.stuAns.length ? 1:2 //未作答
+                        //let index = 0
+                        //for (let items of this.examInfo.stuAns) {
+                        //    if (items.length == 0) {
+                        //        index++
+                        //    }
+                        //}
+                        if (this.examInfo.stuAns[0] == undefined) {
+                            this.testState = 1 //未作答
                         } else {
                             this.testState = 2 //未评分
                         }
@@ -289,301 +289,303 @@
 </script>
 
 <style scoped>
-        .lesson-test-report {
-            min-height: 600px;
-        }
-
-        .scoreboard {
-            width: 100%;
-            /*height: 638px;*/
-            background: rgb(240, 240, 240);
-            /*border: 1px solid rgba(0, 0, 0, 0.1);*/
-            border-radius: 8px;
-            padding: 44px 50px;
-        }
-
-            .scoreboard .ivu-card {
-                margin-bottom: 20px;
-            }
-
-        .card-title {
-            font-size: 16px;
-            color: rgb(109, 114, 120);
-        }
-
-        .myscore {
-            font-size: 60px;
-            font-weight: 700;
-            /*font-family: Arial, Helvetica, sans-serif;*/
-            color: rgb(72, 72, 72);
-        }
-
-        .card-content {
-            text-align: center;
-        }
-
-        .score-card {
-            height: 140px;
-        }
-
-        .comment-card {
-            padding-bottom: 20px;
-        }
-        /*.chart-card {
-      height: 550px;
-    }*/
-        .keypoint {
-            color: #03966a;
-        }
-
+    .lesson-test-report {
+        min-height: 600px;
+    }
+
+    .scoreboard {
+        width: 100%;
+        /*height: 638px;*/
+        background: rgb(240, 240, 240);
+        /*border: 1px solid rgba(0, 0, 0, 0.1);*/
+        border-radius: 8px;
+        padding: 44px 50px;
+    }
+
+        .scoreboard .ivu-card {
+            margin-bottom: 20px;
+        }
+
+    .card-title {
+        font-size: 16px;
+        color: rgb(109, 114, 120);
+    }
+
+    .myscore {
+        font-size: 60px;
+        font-weight: 700;
+        /*font-family: Arial, Helvetica, sans-serif;*/
+        color: rgb(72, 72, 72);
+    }
+
+    .card-content {
+        text-align: center;
+    }
+
+    .score-card {
+        height: 140px;
+    }
+
+    .comment-card {
+        padding-bottom: 20px;
+    }
+
+    .chart-card {
+        z-index: 1
+    }
+
+    .keypoint {
+        color: #03966a;
+    }
+
+    .difficulty-rate {
+        text-align: center;
+        margin-top: 20px;
+        font-size: 32px;
+        /*font-family: Arial, Helvetica, sans-serif;*/
+        font-weight: 700;
+    }
+
+    .testReport-subject {
+        position: absolute;
+        right: 0px;
+        top: 85px;
+        border: solid 1px rgba(0, 0, 0, 0.2);
+        padding: 0px 20px;
+        border-radius: 4px;
+        font-size: 20px;
+    }
+
+    .subject-title {
+        color: #24b880 !important;
+    }
+
+    @media screen and (max-width: 1366px) {
         .difficulty-rate {
-            text-align: center;
-            margin-top: 20px;
-            font-size: 32px;
-            /*font-family: Arial, Helvetica, sans-serif;*/
-            font-weight: 700;
-        }
-
-        .testReport-subject {
-            position: absolute;
-            right: 0px;
-            top: 85px;
-            border: solid 1px rgba(0, 0, 0, 0.2);
-            padding: 0px 20px;
-            border-radius: 4px;
-            font-size: 20px;
-        }
-
-        .subject-title {
-            color: #24b880 !important;
-        }
-
-        @media screen and (max-width: 1366px) {
-            .difficulty-rate {
-                margin-top: 10px !important;
-                line-height: 30px;
-                font-size: 30px;
-            }
-
-            .ivu-rate {
-                white-space: nowrap;
-            }
-        }
-
-        .qcontent {
-            margin-top: 10px;
-            list-style-type: none;
-        }
-
-        .qcol {
-            border-bottom: 1px solid rgba(0, 0, 0, 0.1);
-            padding: 20px 0px;
-            padding-right: 0px;
-        }
-
-        .qtype {
-            color: #6d7278;
-            border: 2px #979797 solid;
-            border-radius: 4px;
-            padding: 2px;
-            text-align: center;
-        }
-
-        .qtypeEn {
-            padding: 2px;
-            font-size: 6px;
-        }
-
-        .qAnsCondition {
-            width: 4%;
-            padding: 2px;
-            text-align: center;
-        }
-
-        .qdesc {
-            color: rgb(72, 72, 72);
-        }
-
-        .qScore {
-            font-weight: 800;
-            color: gray;
-            text-align: right;
-        }
-
-        .qIcon {
-            width: 24px;
-            height: 24px;
-            margin-right: 20px;
-        }
-
+            margin-top: 10px !important;
+            line-height: 30px;
+            font-size: 30px;
+        }
+
+        .ivu-rate {
+            white-space: nowrap;
+        }
+    }
+
+    .qcontent {
+        margin-top: 10px;
+        list-style-type: none;
+    }
+
+    .qcol {
+        border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+        padding: 20px 0px;
+        padding-right: 0px;
+    }
+
+    .qtype {
+        color: #6d7278;
+        border: 2px #979797 solid;
+        border-radius: 4px;
+        padding: 2px;
+        text-align: center;
+    }
+
+    .qtypeEn {
+        padding: 2px;
+        font-size: 6px;
+    }
+
+    .qAnsCondition {
+        width: 4%;
+        padding: 2px;
+        text-align: center;
+    }
+
+    .qdesc {
+        color: rgb(72, 72, 72);
+    }
+
+    .qScore {
+        font-weight: 800;
+        color: gray;
+        text-align: right;
+    }
+
+    .qIcon {
+        width: 24px;
+        height: 24px;
+        margin-right: 20px;
+    }
+
+    .qAnaly {
+        margin-top: 0px;
+        padding-left: 8.5%;
+    }
+
+    @media screen and (max-width: 767px) {
         .qAnaly {
-            margin-top: 0px;
-            padding-left: 8.5%;
-        }
-
-        @media screen and (max-width: 767px) {
-            .qAnaly {
-                padding-left: 4.5%;
-            }
-        }
-
-        .qAnaly .rightAns {
-            color: rgb(20, 114, 199);
-        }
-
-        .qAnserlist {
-            color: gray;
-        }
-
-        .qAnaly .rightAnalys {
-            color: gray;
-        }
-
-        .rightAnsItem {
-            color: rgb(20, 114, 199);
-        }
-
-        .wrongAnsItem {
-            color: rgb(199, 71, 20);
-        }
-
-        .TitleRec1 {
-            position: relative;
-            top: 2px;
-            width: 10px;
-            height: 16px;
-            margin-right: 5px;
-            background-color: rgb(20, 114, 199);
-            float: left;
-        }
-
-        .TitleRec2 {
-            position: relative;
-            top: 2px;
-            width: 10px;
-            height: 16px;
-            margin-right: 5px;
-            float: left;
-            background-color: gray;
-        }
-
-        .TitleRec3 {
-            position: relative;
-            top: 2px;
-            width: 10px;
-            height: 16px;
-            margin-right: 5px;
-            float: left;
-            background-color: gray;
-        }
-
-        .related-question {
-            margin-top: 1%;
-            margin-left: 1.5%;
-        }
-
-            .related-question li {
-                margin-top: 5px;
-            }
-
-        /**對問題進行篩選 */
-        .filterBtn {
-            display: inline-block;
-        }
-
-        .checkAns {
-            display: inline-block;
-            margin-left: 10px;
-        }
-
-            .checkAns input[type="checkbox"] {
-                visibility: hidden;
-                margin-left: -10px;
-            }
-
-            .checkAns:hover {
-                cursor: pointer;
-            }
-
-            .checkAns span {
-                position: relative;
-                z-index: 2;
-                padding: 10px;
-                padding-right: 12px;
-                font-weight: bolder;
-            }
-
-            .checkAns input[type="checkbox"]:checked ~ span {
-                color: #fff;
-                font-weight: bolder;
-            }
-
-            .checkAns input[type="checkbox"]:checked ~ .noAnsBtn {
-                background-color: rgb(183, 183, 183) !important;
-                border: none;
-            }
-
-            .checkAns input[type="checkbox"]:checked ~ .rightBtn {
-                background-color: rgb(20, 114, 199) !important;
-                border: none;
-            }
-
-            .checkAns input[type="checkbox"]:checked ~ .wrongBtn {
-                background-color: rgb(255, 85, 8) !important;
-                border: none;
-            }
-
-        .noAnsBtn,
-        .rightBtn,
-        .wrongBtn {
-            background-color: #fff;
-            position: relative;
-            height: 26px;
-            top: -24px;
-            margin-bottom: -20px;
-            z-index: 1;
-            border-radius: 4px;
-            border: 1px solid rgb(197, 197, 197);
-        }
-
-        .ansDetail,
-        .ansDetail:hover,
-        .closeAnsDetail:hover {
-            float: right;
-            height: 28px;
-            width: 28px;
-            margin-top: -40px;
-            margin-bottom: -40px;
-            color: #03966a;
+            padding-left: 4.5%;
+        }
+    }
+
+    .qAnaly .rightAns {
+        color: rgb(20, 114, 199);
+    }
+
+    .qAnserlist {
+        color: gray;
+    }
+
+    .qAnaly .rightAnalys {
+        color: gray;
+    }
+
+    .rightAnsItem {
+        color: rgb(20, 114, 199);
+    }
+
+    .wrongAnsItem {
+        color: rgb(199, 71, 20);
+    }
+
+    .TitleRec1 {
+        position: relative;
+        top: 2px;
+        width: 10px;
+        height: 16px;
+        margin-right: 5px;
+        background-color: rgb(20, 114, 199);
+        float: left;
+    }
+
+    .TitleRec2 {
+        position: relative;
+        top: 2px;
+        width: 10px;
+        height: 16px;
+        margin-right: 5px;
+        float: left;
+        background-color: gray;
+    }
+
+    .TitleRec3 {
+        position: relative;
+        top: 2px;
+        width: 10px;
+        height: 16px;
+        margin-right: 5px;
+        float: left;
+        background-color: gray;
+    }
+
+    .related-question {
+        margin-top: 1%;
+        margin-left: 1.5%;
+    }
+
+        .related-question li {
+            margin-top: 5px;
+        }
+
+    /**對問題進行篩選 */
+    .filterBtn {
+        display: inline-block;
+    }
+
+    .checkAns {
+        display: inline-block;
+        margin-left: 10px;
+    }
+
+        .checkAns input[type="checkbox"] {
+            visibility: hidden;
+            margin-left: -10px;
+        }
+
+        .checkAns:hover {
             cursor: pointer;
         }
 
-        .closeAnsDetail {
-            float: right;
-            height: 28px;
-            width: 28px;
-            margin-top: -40px;
-            margin-bottom: -40px;
-            color: gray;
-            cursor: pointer;
-        }
-
-        .hideqAnaly {
-            display: none;
+        .checkAns span {
+            position: relative;
+            z-index: 2;
+            padding: 10px;
+            padding-right: 12px;
+            font-weight: bolder;
         }
 
-        .aclassoneloading3 {
+        .checkAns input[type="checkbox"]:checked ~ span {
+            color: #fff;
             font-weight: bolder;
-            position: absolute;
-            text-align: center;
-            top: -70%;
-            right: -40%;
-            font-size: 20px;
-            color: rgba(0, 0, 0, 0.5)
         }
 
-        .vld-overlay {
-            outline: none;
-            border: none
-        }
+        .checkAns input[type="checkbox"]:checked ~ .noAnsBtn {
+            background-color: rgb(183, 183, 183) !important;
+            border: none;
+        }
+
+        .checkAns input[type="checkbox"]:checked ~ .rightBtn {
+            background-color: rgb(20, 114, 199) !important;
+            border: none;
+        }
+
+        .checkAns input[type="checkbox"]:checked ~ .wrongBtn {
+            background-color: rgb(255, 85, 8) !important;
+            border: none;
+        }
+
+    .noAnsBtn,
+    .rightBtn,
+    .wrongBtn {
+        background-color: #fff;
+        position: relative;
+        height: 26px;
+        top: -24px;
+        margin-bottom: -20px;
+        z-index: 1;
+        border-radius: 4px;
+        border: 1px solid rgb(197, 197, 197);
+    }
+
+    .ansDetail,
+    .ansDetail:hover,
+    .closeAnsDetail:hover {
+        float: right;
+        height: 28px;
+        width: 28px;
+        margin-top: -40px;
+        margin-bottom: -40px;
+        color: #03966a;
+        cursor: pointer;
+    }
+
+    .closeAnsDetail {
+        float: right;
+        height: 28px;
+        width: 28px;
+        margin-top: -40px;
+        margin-bottom: -40px;
+        color: gray;
+        cursor: pointer;
+    }
+
+    .hideqAnaly {
+        display: none;
+    }
+
+    .aclassoneloading3 {
+        font-weight: bolder;
+        position: absolute;
+        text-align: center;
+        top: -70%;
+        right: -40%;
+        font-size: 20px;
+        color: rgba(0, 0, 0, 0.5)
+    }
+
+    .vld-overlay {
+        outline: none;
+        border: none
+    }
 </style>

+ 7 - 3
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReportCharts/KeyPointPerformChart.vue

@@ -17,11 +17,14 @@ export default {
       series: [
         {
           name: this.$t('studentWeb.exam.chart.me'),
-          data: [80, 50, 30, 40, 100]
+          //data: [80, 50, 30, 40, 100]
+          data: [0,0,0,0,0]
         },
         {
           name: this.$t('studentWeb.exam.chart.participantAverage'),
-          data: [20, 30, 40, 80, 20]
+          //data: [20, 30, 40, 80, 20]
+            data: [0, 0, 0, 0, 0]
+
         },
        
       ],
@@ -79,7 +82,8 @@ export default {
         },
         xaxis: {
           type: "category",
-          categories: localStorage.getItem('lang')=='tw'?["內積空間", "向量", "矩陣", "行列式", "線性轉換"]:["Inner product space", "vector", "matrix", "determinant", "linear transformation"],
+          //categories: localStorage.getItem('lang')=='tw'?["內積空間", "向量", "矩陣", "行列式", "線性轉換"]:["Inner product space", "vector", "matrix", "determinant", "linear transformation"],
+            categories: ["知识点1", "知识点2", "知识点3", "知识点4", "知识点5"],
           labels: {
             style: {
               colors: ["#000", "#000", "#000", "#000", "#000"],

+ 6 - 3
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReportCharts/RecognizePerformChart.vue

@@ -17,11 +17,13 @@ export default {
       series2: [
         {
           name:this.$t('studentWeb.exam.chart.me'),
-          data: [80, 50, 30, 40, 100, 70]
+              //data: [80, 50, 30, 40, 100, 70]
+            data: [0,0,0,0,0,0]
         },
         {
           name: this.$t('studentWeb.exam.chart.participantAverage'),
-          data: [20, 30, 40, 80, 42, 80]
+          //data: [20, 30, 40, 80, 42, 80]
+            data:[0,0,0,0,0,0]
         }
       ],
 
@@ -78,7 +80,8 @@ export default {
         },
         xaxis: {
           type: "category",
-          categories: localStorage.getItem('lang')=='tw'?["知識", "理解", "應用", "分析", "綜合", "評鑑"]:["Knowledge", "Understanding", "Application", "Analysis", "Integration", "Evaluation"],
+          //categories: localStorage.getItem('lang')=='tw'?["知識", "理解", "應用", "分析", "綜合", "評鑑"]:["Knowledge", "Understanding", "Application", "Analysis", "Integration", "Evaluation"],
+          categories: ["知识", "理解", "应用", "分析", "综合", "评鉴"],
           labels: {
             style: {
               colors: ["#000", "#000", "#000", "#000", "#000", "#000"],

+ 39 - 7
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestPop.vue

@@ -416,22 +416,38 @@
                     this.isLoading = false
                 }, 500)
             },
+            async getItem(data) {
+                let datas = []
+                if (data !== undefined) {
+                    let key = this.$store.getters.getExamInfo.code.split('-')
+                    let code = {
+                        scope: this.$store.getters.getExamInfo.scope,
+                        code: key[(key.length - 1)],
+                        blob: data
+                    }
+                    datas = await this.$evTools.getComposeItem(code)
+                    return datas
+                } else {
+                    return []
+                }
+            },
         },
 
         watch: {
             papers: {
-                handler(newV, oldV) {
+               async handler(newV, oldV) {
                     if (newV.item.length) {
                         this.checkers.length = 0
                         this.closeTest = true
-                        if (this.$store.getters.getCurrentSubject.stuAns.length != 0 && this.$store.getters.getCurrentSubject.stuAns[0].length != 0) {
-                            this.checkers = [...this.$store.getters.getCurrentSubject.stuAns]
-                            console.log('作答信息')
-                            console.log('5645641', JSON.stringify(this.checkers))
-                            console.log(this.papers)
+                        if (this.$store.getters.getCurrentSubject.stuAns[0] !== undefined) {
+                            let data = []
+                            data = await this.getItem(this.$store.getters.getCurrentSubject.stuAns[0])
+                            if (data.length) {
+                                this.checkers = [...data]
+                            } else this.$Message.warning('作答信息错误!')
                             this.closeTest = false
                             } else {
-                            for (let i = 0; i < this.$store.getters.getCurrentSubject.stuAns.length; i++) {
+                            for (let i = 0; i < this.$store.getters.getCurrentSubject.stuScore.length; i++) {
                                     this.checkers == this.checkers.push([])
                                 }
                         }
@@ -458,4 +474,20 @@
 
 <style scoped>
     @import "~@/assets/student-web/component_styles/lesson-testpop.css";
+    .que-item /deep/ table {
+        border-top: 1px solid #ccc;
+        border-left: 1px solid #ccc;
+    }
+
+    .que-item /deep/ table td,
+    table th {
+        border-right: 1px solid #ccc;
+        padding: 3px 5px;
+    }
+
+        .que-item /deep/ table th {
+            border-bottom: 1px solid #ccc;
+            border-right: 1px solid #ccc;
+            text-align: center;
+        }
 </style>

+ 15 - 21
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTest.vue

@@ -1,7 +1,7 @@
 <template>
     <div class="lesson-test">
         <br />
-        <LessonTestPop :papers="selectData" v-if="this.$store.getters.getisOpenLessonTestPopNow"  />
+        <PaperTest :papers="selectData" v-if="this.$store.getters.getisOpenLessonTestPopNow"  />
         <div>
             <EventBasicInfo :paper="paperData" />
             <div v-if="this.$store.getters.getItemTitle.isDone == false && this.$store.getters.getItemTitle.endTime <= '2020.02.10' &&this.$store.getters.getItemTitle.allowRetryNow == false">
@@ -28,7 +28,7 @@
                         {{ item.subject.name }}科试卷
                     </li>
                     <!--试卷是否已作答-->
-                    <li :class="{ unfinished: item.stuAns[0].length == 0 ,finished:item.stuAns[0].length != 0 }">
+                    <li :class="{ unfinished: item.stuAns.length == 0 ,finished:item.stuAns.length != 0 }">
                         <Icon class="doneicon" type="ios-checkmark" size="36" />
                     </li>
                 </ul>
@@ -59,13 +59,13 @@
     import "vue-loading-overlay/dist/vue-loading.css";
     import EventBasicInfo from "../../EventBasicInfo";
     import LessonTestReport from "./LessonTestReport";
-    import LessonTestPop from "./LessonTestPop";
+    import PaperTest from "./PaperTest";
     export default {
-        name: "LessonTest",
+        name: "PaperView",
         components: {
             EventBasicInfo,
             LessonTestReport,
-            LessonTestPop,
+            PaperTest,
             Load
         },
         created() {
@@ -104,20 +104,19 @@
                         school: paper.school
                     }
                     this.$api.studentWeb.FindStudentPaper(req).then(res => {
-                        let resData = res.props
-                        let sub = []
-                        for (let item of resData) {
+                        let resData = res
+                        for (let item of resData.papers) {
                             if (item.scope) {
                                 this.paperData.push(item)
-                            } else {
-                                sub = item
-                            }
+                            } 
                         }
                         for (let i = 0; i < this.paperData.length; i++) {
-                            this.paperData[i].subject = sub.subjects[i]
-                            this.paperData[i].stuAns = res.stuAns[i]
-                            this.paperData[i].stuScore = res.stuScore[i]
+                            this.paperData[i].subject = resData.subjects[i]
+                            this.paperData[i].stuAns = resData.stuAns[i]
+                            this.paperData[i].stuScore = resData.stuScore[i]
                         }
+                        console.log('已有数据',this.selectData)
+                        this.opentestWithSubject(this.paperData[0])
                     })
                 }
             },
@@ -166,13 +165,7 @@
                     this.chooseData = data
                     this.isLoad = false
                     if (this.selectData.item.length > 0) {
-                        let k = 0
-                        for (let item of data.stuAns) {
-                            if (item.length == 0) {
-                                k++
-                            }
-                        }
-                        if (k != data.stuAns.length) {
+                        if (data.stuAns[0] !== undefined) {
                             this.isExamDown = true
                         }
                         this.$store.commit("SetPaperInfo", this.selectData)
@@ -194,6 +187,7 @@
         watch: {
             $route: {
                 handler(val, oldval) {
+                    console.log('122112221212125251')
                     this.isExamDown = false
                     this.examData = []
                     this.getPaperData()

+ 2 - 18
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/composePaper.vue

@@ -38,26 +38,10 @@
         methods: {
             async getInfo() {
                 this.examInfo = []
-                await this.initEditor()
+                this.initEditor()
                 if (this.textData.length > 0) {
                     this.examInfo = [...this.textData]
-                    let paperInfo = []
-                    paperInfo = await this.getItem()
-                    if (paperInfo.length) {
-                        this.editor.txt.html(paperInfo[0])
-                    }
-                }
-            },
-            getItem() {
-                if (this.examInfo.length) {
-
-                    let key = this.$store.getters.getExamInfo.code.split('-')
-                    let code = {
-                        scope: this.$store.getters.getExamInfo.scope,
-                        code: key[(key.length - 1)],
-                        blob: this.examInfo[0]
-                    }
-                    return this.$evTools.getComposeItem(code)
+                    this.editor.txt.html(this.examInfo[0])
                 }
             },
             initEditor() {

+ 0 - 29
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventList.vue

@@ -251,35 +251,6 @@
 
         components: { PreviewProgressPie },
         watch: {
-            /*eventTypeCheckers: function (value) {
-              let countfit = 0;
-
-              for (let i = 0; i < this.mockdata.length; i++) {
-                if (
-                  value == "" &&
-                  this.mockdata[i].eventName.includes(this.search) == true
-                ) {
-                  countfit += 1;
-                } else if (
-                  value == "" &&
-                  this.mockdata[i].eventName.includes(this.search) == false
-                ) {
-                  countfit += 0;
-                } else if (value != "") {
-                  if (
-                    value.includes(this.mockdata[i].eventType) &&
-                    this.mockdata[i].eventName.includes(this.search)
-                  ) {
-                    countfit++;
-                  } else if (value.includes(this.mockdata[i].eventType) == false) {
-                    countfit += 0;
-                  }
-                }
-              }
-              if (countfit == 0 && this.search != "") {
-                this.isListNoItem = true;
-              } else this.isListNoItem = false;
-            },*/
             search: function (value) {
                 let countfit = 0;
                 for (let i = 0; i < this.eventList.length; i++) {

+ 13 - 7
TEAMModelOS/ClientApp/src/components/vote/BaseVoteForm.vue

@@ -5,16 +5,15 @@
                 <Input :class="!voteFormEdit ? 'vote-form-disabled':''" v-model="voteForm.name" placeholder="请输入投票名称"></Input>
             </FormItem>
             <FormItem label="投票对象" prop="targetClassIds">
+				<RadioGroup v-model="classType" @on-change="onClassTypeChange" v-if="voteFormEdit">
+				        <Radio label="private">个人班级</Radio>
+				        <Radio label="school">校本班级</Radio>
+				</RadioGroup>
 				<div v-if="!voteFormEdit && curVoteItem" class="vote-class">
 					<span v-for="item in curVoteItem.targetClassIds" class="vote-class-item">{{ getTargetName(item) }}</span>
 				</div>
 				<Select multiple v-model="voteForm.targetClassIds" :class="!voteFormEdit ? 'vote-form-disabled':''" placeholder="请选择投票发布对象" not-found-text="暂未创建班级" v-else>
-				   <OptionGroup label="个人班级">
-				   	<Option v-for="item in classRooms.filter(i=>i.scope === 'private')" :value="item.id" :key="item.id">{{ item.name }}</Option>
-				   </OptionGroup>
-				   <OptionGroup label="校本班级">
-				   	<Option v-for="item in classRooms.filter(i=>i.scope === 'school')" :value="item.id" :key="item.id">{{ item.name }}</Option>
-				   </OptionGroup>
+				   	<Option v-for="item in classRooms.filter(i=>i.scope === classType)" :value="item.id" :key="item.id">{{ item.name }}</Option>
 				</Select>
             </FormItem>
 			
@@ -84,6 +83,7 @@
         },
         data() {
             return {
+				classType:'private',
 				curVoteItem:null,
                 isAdd:true,
                 isEdit: false,
@@ -169,7 +169,9 @@
 			this.getClassrooms(this.userInfo.TEAMModelId).then(res => this.classRooms = res)
 		},
         methods: {
-			
+			onClassTypeChange(val){
+				this.voteForm.targetClassIds = []
+			},
 			onChangeRange(arr) {
 				if(arr[0] === ''){
 					this.voteForm.rangeTime = null
@@ -444,6 +446,10 @@
                 this.voteOptions = item.options.map((item, index) => index)
                 this.$nextTick(() => {
                     this.initEditors()
+					if(item.targetClassIds.length){
+						let isExist = this.classRooms.filter(i => i.id === item.targetClassIds[0])
+						this.classType = isExist ? isExist[0].scope : 'private'
+					}
 					this.curVoteItem = JSON.parse(JSON.stringify(item))
                 })
             },

+ 0 - 2
TEAMModelOS/ClientApp/src/store/module/studentWeb.js

@@ -139,8 +139,6 @@ export default {
             state.currentQuestionNo = no;
         },
         SetPaperInfo(state, data) {
-            console.log('存入数据')
-            console.log(data)
             state.paperInfo = {}
             state.paperInfo = data
         },

+ 3 - 4
TEAMModelOS/ClientApp/src/utils/editorTools.js

@@ -13,7 +13,7 @@ export default {
 		editor.config.uploadImgShowBase64 = true;
 		editor.config.uploadImgMaxLength = 5 // 一次最多上传 5 个图片
 		editor.config.showLinkImg = false
-		editor.config.showFullScreen = false
+		editor.config.showFullScreen = true
 		editor.config.menus = [
 		    'bold',
 		    'italic',
@@ -297,11 +297,10 @@ export default {
 	
 			clickHandler() {
 				console.log(Modal)
-				Modal.props.fullscreen.default = true
-				Modal.props.footerHide.default = true
+				// Modal.props.fullscreen.default = true
 				Modal.info({
 					width:1300,
-					footerHide:true,
+					okText:'取消',
 					render: (h) => {
 						return h('div',{
 							style:{

+ 14 - 1
TEAMModelOS/ClientApp/src/utils/evTools.js

@@ -216,6 +216,7 @@ export default {
 	
 	/* 获取完整的试卷数据 */
 	getFullPaper(paper){
+		console.log('evTools换取试卷' , paper)
 		return new Promise(async (r,j) => {
 			let blobHost = paper.scope === 'school' ?  JSON.parse(decodeURIComponent(localStorage.school_profile, "utf-8")).blob_uri :  JSON.parse(decodeURIComponent(localStorage.user_profile, "utf-8")).blob_uri
 			// 根据试卷的Blob地址 去读取JSON文件
@@ -238,6 +239,7 @@ export default {
 							itemJson.exercise.id = itemJson.id 
 							itemJson.exercise.pid = itemJson.pid 
 							itemJson.exercise.score = item.scoring ? item.scoring.score : 0,
+							console.log(this.getImgSrc(itemJson.exercise.question))
 							resolve(itemJson.exercise)
 						}))
 					})
@@ -248,6 +250,8 @@ export default {
 							resItem.children = []
 							if(resItem.pid){
 								let pItem = res.filter(i => i.id === resItem.pid)[0]
+								console.log(resItem.pid)
+								console.log(pItem)
 								pItem.children.push(resItem)
 								pItem.score = pItem.score + resItem.score
 							}
@@ -265,13 +269,13 @@ export default {
 	
 	/* 获取完整的试卷数据 */
 	getStuPaper(paper){
+		console.log('evTools换取学生试卷' , paper)
 		return new Promise(async (r,j) => {
 			let blobHost = JSON.parse(decodeURIComponent(localStorage.student_profile, "utf-8")).blob_uri
 			let splitHost = blobHost.split('/')
 			// 根据试卷的Blob地址 去读取JSON文件
 			let sasString = paper.scope === 'school' ?  await $tools.getSchoolSas(paper.code) : await $tools.getPrivateSas(paper.code)
 			try {
-				console.log(sasString.url + '/' + paper.code + paper.blob + '/index.json' + sasString.sas)
 				let jsonInfo = await $tools.getFile(sasString.url + '/' + paper.code + paper.blob + '/index.json' + sasString.sas)
 				let jsonData = JSON.parse(jsonInfo)
 				// 获取试卷包含的试题数据并包装好
@@ -318,6 +322,7 @@ export default {
 			// 根据试卷的Blob地址 去读取JSON文件
 			let sasString = paper.scope === 'school' ? await $tools.getSchoolSas(paper.code) : await $tools.getPrivateSas(paper.code)
 			try {
+				console.log(paper.blob + sasString.sas)
 				let jsonInfo = await $tools.getFile(paper.blob + sasString.sas)
 				let jsonData = JSON.parse(jsonInfo)
 				// 获取试卷包含的试题数据并包装好
@@ -336,4 +341,12 @@ export default {
 		var r = /<[^>]*>|/g;
 		return html.replace(r, '')
 	},
+	
+	getImgSrc(richtext) {
+	    let imgList = [];
+	    richtext.replace(/<video [^>]*src=['"]([^'"]+)[^>]*>/g, (match, capture) => {
+	          imgList.push(capture);
+	    });
+	    return imgList;
+	}
 }

+ 5 - 7
TEAMModelOS/ClientApp/src/view/classrecord/ClassRecord.vue

@@ -693,10 +693,9 @@
                     role: 'teacher'
                 }).then(
                     (res) => {
-                        if (res.error == null) {
-                            res.result.data.sas = '?' + res.result.data.sas
-                            let sasRes1 = res.result.data
-                            this.teacherSas = sasRes1.sas
+                        if (!res.error) {
+                            res.sas = '?' + res.sas
+                            this.teacherSas = res.sas
                         } else {
                             this.$Message.error('获取Blob授权失败')
                         }
@@ -712,9 +711,8 @@
                 }).then(
                     (res) => {
                         if (!res.error) {
-                            res.result.data.sas = '?' + res.result.data.sas
-                            let sasRes2 = res.result.data
-                            this.schoolSas = sasRes2.sas
+                            res.sas = '?' + res.sas
+                            this.schoolSas = res.sas
                             this.playerOptions.sources[0].src += this.schoolSas
                         } else {
                             this.$Message.error('获取Blob授权失败')

+ 20 - 22
TEAMModelOS/ClientApp/src/view/evaluation/bank/ExerciseList.vue

@@ -116,17 +116,13 @@
 								<span class="explain-title">【答ㅤ案】</span>
 								<div class="item-explain-details">
 									<!-- 问答题答案 -->
-									<div v-if="item.type === 'subjective'">
+									<div v-if="item.type === 'subjective' || item.type === 'complete'">
 										<span v-for="(answer, index) in item.answer" :key="index" v-html="item.answer.length ? answer : '未设置答案'"></span>
 									</div>
 									<!-- 问答题答案 -->
 									<div v-else-if="item.type === 'judge'">
 										<span>{{ item.answer.length ? (item.answer[0] === 'A' ? '正确' : '错误') : '未设置答案' }}</span>
 									</div>
-									<!-- 填空题答案 -->
-									<div v-else-if="item.type === 'complete'">
-										<span :class="[ item.type === 'complete' ? 'item-answer-item' : '',]" v-for="(answer, index) in item.answer" :key="index" v-html="answer"></span>
-									</div>
 									<!-- 其余题型答案 -->
 									<div v-else>
 										<span :class="[
@@ -172,10 +168,10 @@
 					<!--<span class="item-tools-info" style="border:0">更新时间:{{ formatDateTime(new Date(item.createTime * 1000)) }}</span>-->
 					<!--<Button type="info" :style="{backgroundColor:basketList.all.indexOf(item) > -1 ? '#bbbbbb' : ''}" @click="handleChoose(item)">{{basketList.all.indexOf(item) > -1 ? '已选入' : '选题'}} </Button>-->
 
-					<Button type="text" @click.stop="handleEdit(item)" v-if="($access.can('admin.*||exercise-upd') ||  (filterOrigin !== schoolCode))" icon="md-create"
-					 style="margin-right: 10px">编辑</Button>
-					<Button type="text" @click.stop="handleDelete(item)" v-if="($access.can('admin.*||exercise-upd') ||  (filterOrigin !== schoolCode))" icon="md-trash"
-					 style="margin-right: 10px">删除</Button>
+					<Button type="text" @click.stop="handleEdit(item)" v-if="($access.can('admin.*||exercise-upd') ||  (filterOrigin !== schoolCode))"
+					 icon="md-create" style="margin-right: 10px">编辑</Button>
+					<Button type="text" @click.stop="handleDelete(item)" v-if="($access.can('admin.*||exercise-upd') ||  (filterOrigin !== schoolCode))"
+					 icon="md-trash" style="margin-right: 10px">删除</Button>
 				</div>
 			</div>
 		</div>
@@ -219,7 +215,7 @@
 					compose: "综合题",
 				},
 				exersicesDiff: ["容易", "较易", "一般", "较难", "困难"],
-				exersicesField:["知识", "理解", "应用", "分析", "综合", "评鉴"],
+				exersicesField: ["知识", "理解", "应用", "分析", "综合", "评鉴"],
 				diffColors: ["#32CF74", "#E8BE15", "#F19300", "#EB5E00", "#D30000"],
 				filterType: ["all"],
 				filterOrigin: "",
@@ -261,7 +257,7 @@
 			/** 获取区班校信息 */
 			getSchoolInfo() {
 				this.dataLoading = true;
-				try{
+				try {
 					this.$store.dispatch("user/getSchoolProfile").then((res) => {
 						let schoolBaseInfo = res.school_base;
 						if (schoolBaseInfo) {
@@ -279,11 +275,11 @@
 						}
 						this.doFilter();
 					});
-				}catch(e){
+				} catch (e) {
 					// 当前未加入学校
 					this.doFilter();
 				}
-				
+
 			},
 
 			/* 获取BLOB所有试题LIST */
@@ -321,8 +317,10 @@
 				/** 定义查询接口的参数规格 */
 				this.filterParams = {
 					"@DESC": this.filterSort,
-					code: (this.isShowSchoolBank || (this.filterOrigin === this.schoolCode)) ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId,
-					periodId: (this.isShowSchoolBank || (this.filterOrigin === this.schoolCode)) && this.periodList.length ? [this.periodList[this.filterPeriod].id] : [],
+					code: (this.isShowSchoolBank || (this.filterOrigin === this.schoolCode)) ? this.$store.state.userInfo.schoolCode :
+						this.$store.state.userInfo.TEAMModelId,
+					periodId: (this.isShowSchoolBank || (this.filterOrigin === this.schoolCode)) && this.periodList.length ? [this.periodList[
+						this.filterPeriod].id] : [],
 					"gradeIds[*]": (this.isShowSchoolBank || (this.filterOrigin === this.schoolCode)) ?
 						this.deleteFalse(this.filterGrade) : [],
 					subjectId: (this.isShowSchoolBank || (this.filterOrigin === this.schoolCode)) ?
@@ -331,7 +329,7 @@
 					type: this.deleteFalse(this.filterType),
 					field: this.deleteFalse(this.filterField),
 					scope: this.curScope,
-					pid:null
+					pid: null
 				};
 				this.getExerciseList(this.filterParams);
 			},
@@ -636,11 +634,11 @@
 									sasData.sas,
 									this.curScope
 								);
-								let blobList = await this.getItemFiles(`item/${item.id}`,containerClient)
+								let blobList = await this.getItemFiles(`item/${item.id}`, containerClient)
 								let files = blobList.blobList.map(i => i.blob)
 								console.log(blobList)
 								if (!res.error) {
-									this.deleteItemFiles(files,containerClient).then((e) => {
+									this.deleteItemFiles(files, containerClient).then((e) => {
 										this.$Message.success("删除成功");
 										this.doFilter();
 									}).catch(err => {
@@ -665,9 +663,9 @@
 					},
 				});
 			},
-			
+
 			// 获取当前试题内所有blob文件包含音视频
-			getItemFiles(path,containerClient) {
+			getItemFiles(path, containerClient) {
 				return new Promise(async (r, j) => {
 					containerClient.listBlob({
 						prefix: path
@@ -682,9 +680,9 @@
 					)
 				})
 			},
-			
+
 			// 批量删除所有题目内文章
-			deleteItemFiles(files,containerClient){
+			deleteItemFiles(files, containerClient) {
 				return new Promise(async (r, j) => {
 					containerClient.deleteBlobBatch(files).then(
 						(res) => {

+ 3 - 0
TEAMModelOS/ClientApp/src/view/evaluation/bank/TestPaperList.vue

@@ -119,6 +119,7 @@
 		methods: {
 			
 			async onPreviewPaper(paper){
+				this.dataLoading = true
 				let curPaper = paper
 				try {
 					// 获取完整试卷数据再跳转编辑页面
@@ -146,8 +147,10 @@
 						createType:'manual'
 					}
 					this.isPreview = true
+					this.dataLoading = false
 				} catch (e) {
 					console.log(e)
+					this.dataLoading = false
 					this.$Message.error('获取试卷数据失败!请稍后再试!')
 				}
 			},

+ 5 - 10
TEAMModelOS/ClientApp/src/view/evaluation/components/BaseChild.vue

@@ -24,17 +24,12 @@
 				<span class="explain-title">【答ㅤ案】</span>
 				<div class="item-explain-details">
 					<!-- 问答题答案 -->
-					<div v-if="item.type === 'subjective'">
-						<span v-for="(answer,index) in item.answer" :key="index" v-html="item.answer.length ? answer : '未设置答案'"></span>
+					<div v-if="item.type === 'subjective' || item.type === 'complete'">
+						<span v-for="(answer,index) in item.answer" :key="index" v-html="item.answer && item.answer.length ? answer : '未设置答案'"></span>
 					</div>
 					<!-- 问答题答案 -->
 					<div v-else-if="item.type === 'judge'">
-						<span>{{ item.answer.length ? (item.answer[0] === 'A' ? '正确' : '错误') : '未设置答案' }}</span>
-					</div>
-					<!-- 填空题答案 -->
-					<div v-else-if="item.type === 'complete'">
-						<span :class="[ item.type === 'complete' ? 'item-answer-item':'']" v-for="(answer,index) in item.answer" :key="index"
-						 v-html="answer"></span>
+						<span>{{ item.answer && item.answer.length ? (item.answer[0] === 'A' ? '正确' : '错误') : '未设置答案' }}</span>
 					</div>
 					<!-- 其余题型答案 -->
 					<div v-else>
@@ -53,7 +48,7 @@
 			<div class="item-explain">
 				<span class="explain-title">【知识点】</span>
 				<div class="item-explain-details">
-					<span v-if="!item.points.length">暂未绑定知识点</span>
+					<span v-if="!item.points || !item.points.length">暂未绑定知识点</span>
 					<div v-else>
 						<span v-for="(point,index) in item.points" :key="index" class="item-point-tag">
 							<span>{{ point }}</span>
@@ -89,7 +84,7 @@
 			}
 		},
 		created() {
-			if(this.children.length){
+			if(this.children && this.children.length){
 				console.log(this.totalScore)
 				console.log(this.children)
 				this.children.forEach(i => {

+ 1 - 3
TEAMModelOS/ClientApp/src/view/evaluation/components/BaseCreateChild.vue

@@ -243,9 +243,7 @@
 						exerciseItem.type = this.exersicesType;
 						exerciseItem.level = +this.exersicesDiff;
 						exerciseItem.explain = this.analysisContent;
-						exerciseItem.answer = this.$refs.complete.optionsContent.map(
-							(item) => item.value
-						);
+						exerciseItem.answer = [this.$refs.complete.answerContent];
 						break;
 					case "subjective":
 						exerciseItem.question = this.$refs.subjective.stemContent;

+ 1 - 3
TEAMModelOS/ClientApp/src/view/evaluation/components/BaseEditExercise.vue

@@ -271,9 +271,7 @@
 						exerciseItem.option = [];
 						exerciseItem.type = this.exersicesType;
 						exerciseItem.level = +this.exersicesDiff;
-						exerciseItem.answer = this.$refs.complete._data.optionsContent.map(
-							(item) => item.value
-						);
+						exerciseItem.answer = this.$refs.complete._data.answerContent;
 						break;
 					case "subjective":
 						exerciseItem.question = this.$refs.subjective._data.stemContent;

+ 2 - 7
TEAMModelOS/ClientApp/src/view/evaluation/components/BaseExerciseList.vue

@@ -2,7 +2,7 @@
 	<div class="components-el-container">
 		<!-- 题目列表部分 -->
 		<div v-if="exerciseList.length === 0" class="no-data-text">
-			<img src="../../../assets/icon/no_data.svg" width="120" />
+			<img src="@/assets/icon/no_data.svg" width="120" />
 			<span style="margin-top:15px;color:#808080">暂无数据</span>
 		</div>
 		<div class="content-wrap" ref="mathJaxContainer" v-else>
@@ -80,18 +80,13 @@
 									<span class="explain-title">【答ㅤ案】</span>
 									<div class="item-explain-details">
 										<!-- 问答题答案 -->
-										<div v-if="item.type === 'subjective'">
+										<div v-if="item.type === 'subjective' || item.type === 'complete'">
 											<span v-for="(answer,index) in item.answer" :key="index" v-html="item.answer.length ? answer : '未设置答案'"></span>
 										</div>
 										<!-- 问答题答案 -->
 										<div v-else-if="item.type === 'judge'">
 											<span>{{ item.answer.length ? (item.answer[0] === 'A' ? '正确' : '错误') : '未设置答案' }}</span>
 										</div>
-										<!-- 填空题答案 -->
-										<div v-else-if="item.type === 'complete'">
-											<span :class="[ item.type === 'complete' ? 'item-answer-item':'']" v-for="(answer,index) in item.answer"
-											 :key="index" v-html="answer"></span>
-										</div>
 										<!-- 其余题型答案 -->
 										<div v-else>
 											<span :class="[ item.type === 'complete' ? 'item-answer-item':'']" v-for="(answer,index) in item.answer"

+ 2 - 1
TEAMModelOS/ClientApp/src/view/evaluation/index/CreateExercises.less

@@ -6,7 +6,7 @@
 
     .ev-container .w-e-text-container {
 		z-index:0 !important;
-        height:250px !important;
+        min-height:250px !important;
     }
 
     .ev-container .ev-title {
@@ -169,6 +169,7 @@ exersices-attr-diff {
     }
     .option-editor .w-e-text-container {
         border:none !important;
+		min-height: auto !important;
         height:auto !important;
 		z-index: 1 !important;
 		position: unset !important;

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

@@ -287,9 +287,7 @@
 						exerciseItem.type = this.exersicesType;
 						exerciseItem.level = +this.exersicesDiff;
 						exerciseItem.explain = this.analysisContent;
-						exerciseItem.answer = this.$refs.complete.optionsContent.map(
-							(item) => item.value
-						);
+						exerciseItem.answer = [this.$refs.complete.answerContent];
 						break;
 					case "subjective":
 						exerciseItem.question = this.$refs.subjective.stemContent;

+ 65 - 269
TEAMModelOS/ClientApp/src/view/evaluation/types/BaseCompletion.vue

@@ -1,291 +1,87 @@
 <template>
-    <div>
-        <div class="exersices-content">
-            <span class="add-underline"><Button type="primary" @click="addOption()" v-show="isStemFocus">添加填空横线</Button></span>
-            <IconText :text="'题目'" :color="'#2d8cf0'" :icon="'ios-create'" style="margin-bottom:15px;"></IconText>
-            <div>
-                <div ref="completionEditor" id="completionEditor" style="text-align:left"></div>
-            </div>
-        </div>
-        <div class="exersices-option">
-            <IconText :text="'填空选项'" :color="'#FF871C'" :icon="'md-reorder'"></IconText>
-            <div v-for="(item,index) in optionsIndexArr" :key="index" :class="['editor-wrap-'+item,'editor-wrap']" style="margin-top:10px;display:flex">
-				<span class="fl-center option-delete" @click="deleteOption(index,item)">
-					<Icon type="md-remove-circle" /></span>
-                <span class="fl-center option-order">{{'空0'+(index+1)}}</span>
-                <div :ref="'editor'+index" style="text-align:left" class="option-editor" @click="optionClick(index)"></div>
-                <span :class="['fl-center', 'option-setting']" style="display:none;background:transparent;cursor:auto"></span>
-            </div>
-            <!--<p class="option-add"><span @click="addOption()">+ 添加选项 </span></p>-->
-        </div>
-    </div>
+	<div>
+		<div class="exersices-content">
+			<IconText :text="'填空题题干'" :color="'#2d8cf0'" :icon="'ios-create'" style="margin-bottom:15px;"></IconText>
+			<div>
+				<div ref="editor" style="text-align:left"></div>
+			</div>
+		</div>
+		<div class="exersices-option">
+			<IconText :text="'参考答案'" :color="'#FF871C'" :icon="'md-reorder'"></IconText>
+			<div style="margin-top:15px;">
+				<div ref="answerEditor" style="text-align:left"></div>
+			</div>
+		</div>
+	</div>
 </template>
 <script>
-    import E from 'wangeditor'
-    import IconText from '@/components/evaluation/IconText.vue'
-    export default {
-        components: {
-            IconText
-        },
-        props: ['editInfo'],
-        data() {
-            return {
-                options: [],
-                optionsContent: [],
-                initFlag: true,
-				isStemFocus:false,
-                trueIndex: 0,
-                stemContent: '',
-                stemEditor: null,
-                answerContent: [],
-                linesIndexArr: [],
-                optionsIndexArr: [],
-            }
-        },
-        created() {
-            // 编辑状态下回显
-            
-        },
-        methods: {
-            // 设置正确答案
-            settingAnswer(index) {
-                this.trueIndex = index
-            },
-            // 下划线点击事件
-            lineClick(e) {
-                console.log(e)
-            },
-            // 删除选项
-            deleteOption(index) {
-                this.$Message.warning('请在题目编辑框内删除对应横线即可')
-            },
-            // 选项输入框点击事件
-            optionClick(index) {
-                let allToolbars = document.getElementsByClassName('option-editor')
-                let that = this
-                for (let i = 0; i < allToolbars.length; i++) {
-					console.log(allToolbars[i])
-                    allToolbars[i].children[0].style.visibility = 'hidden'
-                }
-                setTimeout(function() {
-                    let currentToolBar = that.$refs['editor' + index][0].children[0]
-                    if(currentToolBar.clientHeight > 50){
-                    	currentToolBar.style.top = '-90px'
-                    }
-					currentToolBar.style.visibility = 'visible'
-                }, 100)
-            },
+	import E from 'wangeditor'
+	import IconText from '@/components/evaluation/IconText.vue'
+	export default {
+		components: {
+			IconText
+		},
+		props: ['editInfo'],
+		data() {
+			return {
+				stemContent: '',
+				stemEditor: null,
+				answerContent: '',
+				answerEditor: null
 
-            // 添加选项
-            addOption() {
-				if(this.linesIndexArr.length > 7){
-					this.$Message.warning('最多添加8个空格!')
-				}else{
-					let that = this
-					let newIndex = this.linesIndexArr.length ? parseInt(this.linesIndexArr[this.linesIndexArr.length - 1]) + 1 : 0 // 不能重复
-					let newLineIndex = this.linesIndexArr.length // 长度即标记
-					this.optionsIndexArr.push(newIndex) // 选项集合
-					this.linesIndexArr.push(newIndex) // 题干中下划线集合
-					// 插入下划线
-					let addHtml = "&nbsp;<span class='complete-line' data-index=" + newIndex + ' data-answer=' + newIndex + " contenteditable='false'>&#93" + (newLineIndex + 12) + '</span>&nbsp;'
-					this.stemEditor.cmd.do('insertHTML', addHtml)
-					this.stemContent = this.stemContent + addHtml
-					this.$nextTick(() => {
-						console.log(that.$refs)
-					    let editor = new E(that.$refs['editor' + newIndex][0])
-					    // 每个填空选项 数据变化
-					    editor.config.onchange = (html) => {
-					        let codeArr = this.optionsContent.map(item => item.code)
-					        // 如果已经编辑过则 修改选项内容
-					        if (codeArr.indexOf(newIndex) !== -1) {
-					            this.optionsContent[codeArr.indexOf(newIndex)].value = html
-					        } else { // 否则创建新选项
-					            let option = {
-					                code: newIndex,
-					                value: html
-					            }
-					            this.optionsContent.push(option)
-					        }
-					        console.log(this.optionsContent)
-					    },
-						editor.config.onblur = function() {
-							let allToolbars = document.getElementsByClassName('option-editor')
-							for (let j = 0; j < allToolbars.length; j++) {
-								if (allToolbars[j].children.length) {
-									allToolbars[j].children[0].style.visibility = 'hidden'
-								}
-							}
-						},
-						this.$editorTools.initSimpleEditor(editor)
-						editor.create()
-					})
-				}
-                
-            },
-			
-			onStemChange(html){
-				this.stemContent = html
-				
-				// 获取修改后的下划线列表与之前的内容进行对比
-				let linesArr = Array.prototype.slice.call(document.getElementById('completionEditor').getElementsByClassName('complete-line'))
-				let dataSetArr = linesArr.map((item, index) => index)
-				this.linesIndexArr = JSON.parse(JSON.stringify(this.linesIndexArr))
-			
-				// 如果是删除了下划线则删除对应选项输入框
-				if (this.linesIndexArr.length > dataSetArr.length) {
-				    Array.prototype.diff = function(a) {
-				        return this.filter(function(i) { return a.indexOf(i) < 0 })
-				    }
-				    let deleteIndexArr = this.linesIndexArr.diff(dataSetArr) // 获取要删除的选项下标
-				    let optionsArr = Array.prototype.slice.call(document.getElementsByClassName('editor-wrap')) // 获取到所有的选项DOM
-					console.log(deleteIndexArr)
-				    // 对指定选项进行删除操作
-				    this.$nextTick(() => {
-				        deleteIndexArr.forEach(item => {
-				            let deleteDom = document.getElementsByClassName('editor-wrap')[item - 1]
-				            this.optionsIndexArr.splice(this.optionsIndexArr.indexOf(deleteDom), 1)
-				            this.optionsContent.splice(item, 1)
-				            optionsArr.splice(item, 1)
-				        })
-						console.log('删除后的选项')
-						console.log(this.optionsContent)
-				    })
-				}
-				this.linesIndexArr = [...dataSetArr]
-				// 重新渲染下划线的下标
-				linesArr.forEach((item, index) => {
-				    let numCircle = '&#93' + (parseInt(index) + 12) + ''
-				    item.innerHTML = numCircle
-				    item.setAttribute('data-index', index)
-				})
 			}
-
-        },
-
-        mounted() {
-			let that = this
-            let completionEditor = new E(this.$refs.completionEditor)
-
-            // 当填空题型 题干部分插入下划线以及删除下划线监听
-            completionEditor.config.onchange = (html) => {
-                this.onStemChange(html)
-            },
-			completionEditor.config.onfocus = function () {
-				that.isStemFocus = true
+		},
+		methods: {
+			doRender(){
+				this.stemContent = this.editInfo.question
+				this.answerContent = this.editInfo.answer
+				this.stemEditor.txt.html(this.editInfo.question)
+				this.answerEditor.txt.html(this.editInfo.answer[0])
 			}
-			completionEditor.config.onblur = function () {
-				that.isStemFocus = false
+		},
+		mounted() {
+			let stemEditor = new E(this.$refs.editor)
+			stemEditor.config.onchange = (html) => {
+				this.stemContent = html
 			}
-
-			this.$editorTools.addVideoUpload(this, completionEditor)
-			this.$editorTools.addAudio(this, completionEditor)
-			this.$editorTools.initMyEditor(completionEditor)
+			stemEditor.config.uploadImgShowBase64 = true;
+			this.$editorTools.addVideoUpload(this, stemEditor)
+			this.$editorTools.addAudio(this, stemEditor)
+			this.$editorTools.initMyEditor(stemEditor)
 			
-			completionEditor.create()
+			stemEditor.create()
 
-            this.stemEditor = completionEditor
+			let answerEditor = new E(this.$refs.answerEditor)
+			answerEditor.config.onchange = (html) => {
+				this.answerContent = html
+			}
+			answerEditor.config.uploadImgShowBase64 = true;
+			this.$editorTools.addVideoUpload(this, answerEditor)
+			this.$editorTools.addAudio(this, answerEditor)
+			this.$editorTools.initMyEditor(answerEditor)
 			
+			answerEditor.create()
+
+			this.stemEditor = stemEditor
+			this.answerEditor = answerEditor
+
 			if(this.editInfo && this.editInfo.question){
-				console.log('填空题Mount编辑')
-				let n = this.editInfo
-				let that = this
-				this.stemEditor.config.onchange = (html) => {
-				    this.onStemChange(html)
-				},
-				this.onStemChange(n.question)
-				// 回显题干
-				this.stemEditor.txt.html(n.question)
-				this.stemContent = n.question
-				
-				// 回显选项
-				this.optionsIndexArr = n.answer.map((i,index) => index)
-				this.linesIndexArr = n.answer.map((i,index) => index)
-				n.answer.forEach((item, index) => {
-					this.optionsContent.push({ code: index, value: item }) // 填空答案回显
-					this.$nextTick(() => {
-						let editor = new E(that.$refs['editor' + index][0])
-						// 每个填空选项 数据变化
-						editor.config.onchange = (html) => {
-							let codeArr = this.optionsContent.map(item => item.code)
-							// 如果已经编辑过则 修改选项内容
-							if (codeArr.indexOf(index) !== -1) {
-								this.optionsContent[codeArr.indexOf(index)].value = html
-							} else { // 否则创建新选项
-								let option = {
-									code: index,
-									value: html
-								}
-								this.optionsContent.push(option)
-							}
-						},
-						editor.config.onblur = function() {
-							let allToolbars = document.getElementsByClassName('option-editor')
-							for (let j = 0; j < allToolbars.length; j++) {
-								if (allToolbars[j].children.length) {
-									allToolbars[j].children[0].style.visibility = 'hidden'
-								}
-							}
-						},
-						editor.config.uploadImgShowBase64 = true;
-						editor.create()
-						editor.txt.html(item) // 填空答案回显内容
-					})
-				})
+				this.doRender()
 			}
-
-        },
+		},
 		watch:{
 			editInfo:{
 				handler(n){
-					console.log('填空题接收到的数据')
+					console.log('填空题富文本接收到的数据')
 					console.log(n)
 					if(n){
-						let that = this
-						this.stemEditor.config.onchange = (html) => {
-						    this.onStemChange(html)
-						},
-						this.onStemChange(n.question)
-						// 回显题干
-						this.stemEditor.txt.html(n.question)
-						this.stemContent = n.question
-						
-						// 回显选项
-						this.optionsIndexArr = n.answer.map((i,index) => index)
-						this.linesIndexArr = n.answer.map((i,index) => index)
-						n.answer.forEach((item, index) => {
-							this.optionsContent.push({ code: index, value: item }) // 填空答案回显
-							this.$nextTick(() => {
-								let editor = new E(that.$refs['editor' + index][0])
-								// 每个填空选项 数据变化
-								editor.config.onchange = (html) => {
-									let codeArr = this.optionsContent.map(item => item.code)
-									// 如果已经编辑过则 修改选项内容
-									if (codeArr.indexOf(index) !== -1) {
-										this.optionsContent[codeArr.indexOf(index)].value = html
-									} else { // 否则创建新选项
-										let option = {
-											code: index,
-											value: html
-										}
-										this.optionsContent.push(option)
-									}
-								},
-								editor.config.onblur = function() {
-									let allToolbars = document.getElementsByClassName('option-editor')
-									for (let j = 0; j < allToolbars.length; j++) {
-										if (allToolbars[j].children.length) {
-											allToolbars[j].children[0].style.visibility = 'hidden'
-										}
-									}
-								},
-								editor.create()
-								editor.txt.html(item) // 填空答案回显内容
-							})
-						})
+						this.doRender()
 					}
 				}
 			}
 		}
-
-    }
+	}
 </script>
+<style lang="less" scoped>
+	@import"../index/CreateExercises.less";
+</style>

+ 1 - 1
TEAMModelOS/ClientApp/src/view/evaluation/types/BaseCompose.vue

@@ -1,7 +1,7 @@
 <template>
 	<div>
 		<div class="exersices-content">
-			<IconText :text="'题目'" :color="'#2d8cf0'" :icon="'ios-create'" style="margin-bottom:15px;"></IconText>
+			<IconText :text="'综合题题干'" :color="'#2d8cf0'" :icon="'ios-create'" style="margin-bottom:15px;"></IconText>
 			<div>
 				<div ref="editor" style="text-align:left"></div>
 			</div>

+ 1 - 1
TEAMModelOS/ClientApp/src/view/evaluation/types/BaseJudge.vue

@@ -1,7 +1,7 @@
 <template>
 	<div>
 		<div class="exersices-content">
-			<IconText :text="'题目'" :color="'#2d8cf0'" :icon="'ios-create'" style="margin-bottom:15px;"></IconText>
+			<IconText :text="'判断题题干'" :color="'#2d8cf0'" :icon="'ios-create'" style="margin-bottom:15px;"></IconText>
 			<div>
 				<div ref="editor" style="text-align:left"></div>
 			</div>

+ 3 - 3
TEAMModelOS/ClientApp/src/view/evaluation/types/BaseMultiple.vue

@@ -1,7 +1,7 @@
 <template>
 	<div>
 		<div class="exersices-content">
-			<IconText :text="'题目'" :color="'#2d8cf0'" :icon="'ios-create'" style="margin-bottom:15px;"></IconText>
+			<IconText :text="'多选题题干'" :color="'#2d8cf0'" :icon="'ios-create'" style="margin-bottom:15px;"></IconText>
 			<div>
 				<div ref="singleEditor" style="text-align:left"></div>
 			</div>
@@ -167,7 +167,7 @@
 			
 			/* 根据index获取对应选项字母的值 */
 			getOrderCode(index){
-				let wraps = Array.from(document.getElementsByClassName('option-order'))
+				let wraps = Array.from(this.$refs.optionRefs.getElementsByClassName('option-order'))
 				for(let i=0;i<wraps.length;i++){
 					let item = wraps[i]
 					if(+index === +item.dataset.index){
@@ -232,7 +232,7 @@
 			/* 保存试题 获取最新选项数据 */
 			doSave() {
 				// 拿到当前还剩的选项DOM
-				let wraps = Array.from(document.getElementsByClassName('option-editor'))
+				let wraps = Array.from(this.$refs.optionRefs.getElementsByClassName('option-editor'))
 				let arr = []
 				wraps.forEach((item, index) => {
 					// 遍历选项 找到对应的 Editor 然后获取编辑器里面的内容

+ 4 - 4
TEAMModelOS/ClientApp/src/view/evaluation/types/BaseSingle.vue

@@ -1,7 +1,7 @@
 <template>
 	<div>
 		<div class="exersices-content">
-			<IconText :text="'题目'" :color="'#2d8cf0'" :icon="'ios-create'" style="margin-bottom:15px;"></IconText>
+			<IconText :text="'单选题题干'" :color="'#2d8cf0'" :icon="'ios-create'" style="margin-bottom:15px;"></IconText>
 			<div>
 				<div ref="singleEditor" style="text-align:left"></div>
 			</div>
@@ -138,7 +138,7 @@
 			/* 设置正确答案 */
 			settingAnswer(index) {
 				this.optionTrueIndex = index
-				let wraps = Array.from(document.getElementsByClassName('option-order'))
+				let wraps = Array.from(this.$refs.optionRefs.getElementsByClassName('option-order'))
 				for (let i = 0; i < wraps.length; i++) {
 					let item = wraps[i]
 					if (+index === +item.dataset.index) {
@@ -197,7 +197,7 @@
 			/* 保存试题 获取最新选项数据 */
 			doSave() {
 				// 拿到当前还剩的选项DOM
-				let wraps = Array.from(document.getElementsByClassName('option-editor'))
+				let wraps = Array.from(this.$refs.optionRefs.getElementsByClassName('option-editor'))
 				let arr = []
 				console.log(wraps)
 				wraps.forEach((item, index) => {
@@ -241,7 +241,7 @@
 			stemEditor.config.uploadImgShowBase64 = true;
 			this.$editorTools.addVideoUpload(this, stemEditor)
 			this.$editorTools.addAudio(this, stemEditor)
-			// this.$editorTools.addCanvas(this, stemEditor)
+			this.$editorTools.addCanvas(this, stemEditor)
 			this.$editorTools.initMyEditor(stemEditor)
 
 			stemEditor.create()

+ 1 - 5
TEAMModelOS/ClientApp/src/view/evaluation/types/BaseSubjective.vue

@@ -1,7 +1,7 @@
 <template>
 	<div>
 		<div class="exersices-content">
-			<IconText :text="'题目'" :color="'#2d8cf0'" :icon="'ios-create'" style="margin-bottom:15px;"></IconText>
+			<IconText :text="'问答题题干'" :color="'#2d8cf0'" :icon="'ios-create'" style="margin-bottom:15px;"></IconText>
 			<div>
 				<div ref="editor" style="text-align:left"></div>
 			</div>
@@ -24,10 +24,6 @@
 		props: ['editInfo'],
 		data() {
 			return {
-				defaultConfig: {
-					uploadImgShowBase64: true,
-					menus: this.$tools.wangEditorMenu
-				},
 				stemContent: '',
 				stemEditor: null,
 				answerContent: '',

+ 17 - 6
TEAMModelOS/ClientApp/src/view/learnactivity/AutoCreateNew.vue

@@ -11,22 +11,22 @@
 					</CheckboxGroup>
 				</div>
 			</div>
-			<div class="filter-wrap-item animated fadeIn" v-if="includeSchool && filterOrigin.length > 1">
+			<div class="filter-wrap-item" v-if="includeSchool && filterOrigin.length > 1">
 				<span class="filter-title">校本占比 : </span>
 				<div class="filter-content">
 					<InputNumber :max="100" :min="0" :step="10" v-model="schoolRate"></InputNumber>
 					<span style="margin-left: 10px;min-width: 300px;color: #d1d1d1;"> % ( 默认相同比例校本优先 )</span>
 				</div>
 			</div>
-			<div class="filter-wrap-item animated fadeIn" v-if="includeSchool">
+			<div class="filter-wrap-item" v-if="includeSchool">
 				<span class="filter-title">选择学段 : </span>
 				<div class="filter-content">
-					<Select v-model="periodCode">
+					<Select v-model="periodCode" @on-change="onPeriodChange">
 						<Option v-for="item in periodList" :value="item.id" :key="item.id">{{ item.name }}</Option>
 					</Select>
 				</div>
 			</div>
-			<div class="filter-wrap-item animated fadeIn" v-if="includeSchool">
+			<div class="filter-wrap-item" v-if="includeSchool">
 				<span class="filter-title">选择科目 : </span>
 				<div class="filter-content">
 					<Select v-model="subjectCode">
@@ -160,11 +160,20 @@
 					});
 				})
 			},
+			
+			/* 学段切换 */
+			onPeriodChange(val){
+				let curPeriod = this.periodList.filter(i => i.id === val)[0]
+				this.subjectList = curPeriod.subjects
+				this.subjectCode = this.subjectList.length ? this.subjectList[0].id : ''
+			},
 
 			/* 开始组题 */
 			doAutoCreate() {
-				console.log(this.quInfos)
-				console.log(this.filterOrigin)
+				if(this.quInfos.map(i => i.count).filter(j => j === null).length){
+					this.$Message.warning('题目数量不能为空!')
+					return
+				}
 				this.isLoading = true
 				let params = []
 				let copyInfos = JSON.parse(JSON.stringify(this.quInfos))
@@ -175,6 +184,7 @@
 							code: 'Item-' + this.$store.state.userInfo.TEAMModelId,
 							scope: scope,
 							period: '',
+							subject:'',
 							points: [],
 							quInfos: this.filterOrigin.length === 1 ? copyInfos : copyInfos.map(i => {
 								i.count = (i.count - Math.round(i.count * this.schoolRate * 0.01))
@@ -186,6 +196,7 @@
 							code: 'Item-' + this.$store.state.userInfo.schoolCode,
 							scope: scope,
 							period: this.periodCode,
+							subject:this.subjectCode,
 							points: [],
 							quInfos: this.filterOrigin.length === 1 ? copyInfos2 : copyInfos2.map((i, index) => {
 								i.count = Math.round(i.count * this.schoolRate * 0.01)

+ 35 - 0
TEAMModelOS/ClientApp/src/view/learnactivity/ManageEvaluation.less

@@ -217,4 +217,39 @@
     margin-left: 2px;
     border-radius: 5px;
     font-size:12px;
+}
+.overview-box{
+    width: 100%;
+    // min-height: 400px;
+    padding: 10px 20px 10px 10px;
+    display: flex;
+    justify-content: space-between;
+    background: #404040;
+    // margin-top: 5px;
+    .count-box{
+        width: 120px;
+        height: fit-content;
+        text-align: center;
+        background: #404040;
+        padding: 10px 0px;
+        .count-icon{
+            color: white;
+            font-size: 18px;
+            margin-right: 5px;
+            vertical-align: sub;
+            // display: block;
+        }
+        .count-subject-text{
+            display: block;
+            color: white;
+            font-size: 12px;
+        }
+        .count-subject-num{
+            display: block;
+            color: white;
+            font-size: 35px;
+            font-weight: 800;
+        }
+    }
+    
 }

+ 326 - 298
TEAMModelOS/ClientApp/src/view/learnactivity/ManageEvaluation.vue

@@ -61,10 +61,9 @@
                     <div class="test-paper-detail">
                         <vuescroll ref="test-paper-detail" @handle-scroll="checkBackTop">
                             <!--试卷题目信息-->
-                            <TestPaper v-if="evaListShow[curEvaIndex] && evaListShow[curEvaIndex].papers && evaListShow[curEvaIndex].papers[curSubIndex] && evaListShow[curEvaIndex].papers[curSubIndex].item" 
-                            :paper="evaListShow[curEvaIndex].papers[curSubIndex]" style="color:#515a6e;margin-top:-30px;" :isShowTools="false" isExamPaper></TestPaper>
+                            <TestPaper v-if="evaListShow[curEvaIndex] && evaListShow[curEvaIndex].papers && evaListShow[curEvaIndex].papers[curSubIndex] && evaListShow[curEvaIndex].papers[curSubIndex].item" :paper="evaListShow[curEvaIndex].papers[curSubIndex]" style="color:#515a6e;margin-top:-30px;" :isShowTools="false" isExamPaper></TestPaper>
                             <EmptyData v-else style="margin-top:60px;"></EmptyData>
-                            
+
                             <!--返回顶部-->
                             <div class="back-to-top fl-col-center" title="返回顶部" v-if="showBack" @click="handleBackToTop">
                                 <Icon type="ios-arrow-up" />
@@ -74,358 +73,387 @@
                 </div>
                 <!-- 试卷评测打分 -->
                 <div :class="curBarIndex == 0 ? 'animated fadeIn evaluation-base-info':'evaluation-base-info animated fadeOutRight'" v-show="curBarIndex == 0">
-                    <Scoring :examInfo="examPaperList"></Scoring>
+                    <div class="overview-box" style="display:none;">
+                        <div class="count-box">
+                            <span class="count-subject-num">1</span>
+                            <span class="count-subject-text">
+                                <Icon custom="iconfont icon-kecheng" class="count-icon" size="14" style="vertical-align: text-top;" />
+                                学科
+                            </span>
+                        </div>
+                        <div class="count-box">
+                            <span class="count-subject-num">2</span>
+                            <span class="count-subject-text">
+                                <Icon custom="iconfont icon-schedule" class="count-icon" size="14" style="vertical-align: text-top;" />
+                                年级
+                            </span>
+
+                        </div>
+                        <div class="count-box">
+                            <span class="count-subject-num">5</span>
+                            <span class="count-subject-text">
+                                <Icon custom="iconfont icon-class-self" class="count-icon" />
+                                班级
+                            </span>
+
+                        </div>
+                        <div class="count-box">
+                            <span class="count-subject-num">752</span>
+                            <span class="count-subject-text">
+                                <Icon type="ios-people" class="count-icon" />
+                                人数
+                            </span>
+                        </div>
+                        <div class="count-box">
+                            <span class="count-subject-num">602</span>
+                            <span class="count-subject-text">
+                                <Icon type="ios-paper" class="count-icon" />
+                                已作答
+                            </span>
+                        </div>
+                        <div class="count-box">
+                            <span class="count-subject-num">600</span>
+                            <span class="count-subject-text">
+                                <Icon type="md-star" class="count-icon" />
+                                已评分
+                            </span>
+                        </div>
+                    </div>
+                    <Scoring :examInfo="examDetaiInfo"></Scoring>
                 </div>
                 <Loading :top="200" type="1" style="text-align:center" v-show="isLoading"></Loading>
             </div>
         </Split>
-        <Modal v-model="editEvaluationStatus"
-               title="编辑评测"
-               @on-ok="confirmEdit">
+        <Modal v-model="editEvaluationStatus" title="编辑评测" @on-ok="confirmEdit">
             <p>即将跳转到评测编辑页面?</p>
         </Modal>
     </div>
 </template>
 <script>
-    import TestPaper from '@/view/evaluation/index/TestPaper.vue'
-    import Scoring from './Scoring.vue'
-    export default {
-        components: {
-            TestPaper,
-            Scoring
+import TestPaper from '@/view/evaluation/index/TestPaper.vue'
+import Scoring from './Scoring.vue'
+export default {
+    components: {
+        TestPaper,
+        Scoring
+    },
+    data() {
+        return {
+            split1: 0.2,
+            scope: '',//school 校本 private 个人
+            showBack: false,
+            editEvaluationStatus: false,
+            curSubIndex: 0,
+            curBarIndex: 0,
+            curEvaIndex: 0,
+            evaluationList: [],
+            evaListShow: [],
+            examDetaiInfo: {},
+            targetList: [],
+            evaType: [
+                {
+                    value: 'regular',
+                    label: '正规考'
+                },
+                {
+                    value: 'simulation',
+                    label: '模拟考'
+                },
+                {
+                    value: 'normal',
+                    label: '普通考'
+                }
+            ],
+            isLoading: false,
+            filterPeriod: undefined,
+            schoolBase: {
+                period: []
+            }
+        }
+    },
+    methods: {
+        dropdownStates(flag) {
+            if (!flag) this.filterByPeriod()
         },
-        data() {
-            return {
-                split1:0.2,
-                scope:'',//school 校本 private 个人
-                showBack: false,
-                editEvaluationStatus: false,
-                curSubIndex: 0,
-                curBarIndex: 0,
-                curEvaIndex: 0,
-                evaluationList: [],
-                evaListShow:[],
-                examPaperList: {},
-                targetList: [],
-                evaType: [
-                    {
-                        value: 'regular',
-                        label: '正规考'
-                    },
-                    {
-                        value: 'simulation',
-                        label: '模拟考'
+        /**获取type对应的label */
+        getTypeLabel(code) {
+            for (let item of this.evaType) {
+                if (item.value == code) {
+                    return item.label
+                }
+            }
+        },
+        /**
+         * 查找班级课程下的班级
+         * */
+        findClassroom() {
+            if (this.targetList.length == 0) {
+                let requestData = this.$store.state.userInfo.TEAMModelId
+                this.$api.learnActivity.FindClassroomByTeacherId({
+                    code: requestData
+                }).then(
+                    res => {
+                        if (res.error == null) {
+                            this.targetList = res.result.data
+                        } else {
+                            this.$Message.error('API ERROR!')
+                        }
                     },
-                    {
-                        value: 'normal',
-                        label: '普通考'
+                    err => {
+
                     }
-                ],
-                isLoading: false,
-                filterPeriod: undefined,
-                schoolBase: {
-                    period:[]
-                }
+                )
             }
         },
-        methods: {
-            dropdownStates(flag) {
-                if (!flag) this.filterByPeriod()
-            },
-            /**获取type对应的label */
-            getTypeLabel(code) {
-                for (let item of this.evaType ) {
-                    if (item.value == code) {
-                        return item.label
+        /**
+         * 判断是否显示回到顶部按钮
+         * @param vertical
+         * @param horizontal
+         * @param nativeEvent
+         */
+        checkBackTop(vertical, horizontal, nativeEvent) {
+            if (vertical.scrollTop > 100) {
+                this.showBack = true
+            } else {
+                this.showBack = false
+            }
+        },
+        /**vuescroll回到顶部 */
+        handleBackToTop() {
+            this.$refs['test-paper-detail'].scrollTo(
+                {
+                    y: '0'
+                },
+                300
+            )
+        },
+        /**删除评测信息 */
+        deleteEvaluation() {
+            this.$Modal.confirm({
+                title: '删除评测',
+                content: `确认删除${this.evaListShow[this.curEvaIndex].name}吗?`,
+                onOk: () => {
+                    let params = {
+                        id: this.evaListShow[this.curEvaIndex].id,
+                        code: this.evaListShow[this.curEvaIndex].code.replace('Exam-', '')
                     }
-                }
-            },
-            /**
-             * 查找班级课程下的班级
-             * */
-            findClassroom() {
-                if (this.targetList.length == 0) {
-                    let requestData = this.$store.state.userInfo.TEAMModelId
-                    this.$api.learnActivity.FindClassroomByTeacherId({
-                        code:requestData
-                    }).then(
+                    this.isLoading = true
+                    this.$api.learnActivity.DeleteExamInfo(params).then(
                         res => {
                             if (res.error == null) {
-                                this.targetList = res.result.data
+                                let index = this.curEvaIndex
+                                this.selectEvaluation(0)
+                                this.evaListShow.splice(index, 1)
+                                this.$Message.success('删除成功!')
                             } else {
-                                this.$Message.error('API ERROR!')
+                                this.$Message.error('删除失败!')
                             }
                         },
                         err => {
-
+                            this.$Message.error('删除失败!')
                         }
-                    )
-                }
-            },
-            /**
-             * 判断是否显示回到顶部按钮
-             * @param vertical
-             * @param horizontal
-             * @param nativeEvent
-             */
-            checkBackTop(vertical, horizontal, nativeEvent) {
-                if (vertical.scrollTop > 100) {
-                    this.showBack = true
-                } else {
-                    this.showBack = false
+                    ).finally(() => {
+                        setTimeout(() => {
+                            this.isLoading = false
+                        }, 500)
+                    })
                 }
-            },
-            /**vuescroll回到顶部 */
-            handleBackToTop() {
-                this.$refs['test-paper-detail'].scrollTo(
-                    {
-                        y: '0'
-                    },
-                    300
-                )
-            },
-            /**删除评测信息 */
-            deleteEvaluation() {
-                this.$Modal.confirm({
-                    title: '删除评测',
-                    content: `确认删除${this.evaListShow[this.curEvaIndex].name}吗?`,
-                    onOk: () => {
-                        let params = {
-                            id: this.evaListShow[this.curEvaIndex].id,
-                            code: this.evaListShow[this.curEvaIndex].code.replace('Exam-','')
-                        }
-                        this.isLoading = true
-                        this.$api.learnActivity.DeleteExamInfo(params).then(
-                            res => {
-                                if (res.error == null) {
-                                    let index = this.curEvaIndex
-                                    this.selectEvaluation(0)
-                                    this.evaListShow.splice(index, 1)
-                                    this.$Message.success('删除成功!')
-                                } else {
-                                    this.$Message.error('删除失败!')
-                                }
-                            },
-                            err => {
-                                this.$Message.error('删除失败!')
-                            }
-                        ).finally(() => {
-                            setTimeout(() => {
-                                this.isLoading = false
-                            },500)
-                        })
-                    }
-                })
-            },
-            goToCreate() {
-                if (this.$store.state.user.schoolProfile.school_base != undefined) {
-                    if (this.scope == 'school') {
-                        this.$router.push({
-                            name: 'createSchoolEva'
-                        })
-                    } else if (this.scope == 'private') {
-                        this.$router.push({
-                            name: 'createPrivateEva'
-                        })
-                    }
-                } else {
-                    this.$Message.warning("此账号暂未加入任何学校!")
+            })
+        },
+        goToCreate() {
+            if (this.$store.state.user.schoolProfile.school_base != undefined) {
+                if (this.scope == 'school') {
+                    this.$router.push({
+                        name: 'createSchoolEva'
+                    })
+                } else if (this.scope == 'private') {
+                    this.$router.push({
+                        name: 'createPrivateEva'
+                    })
                 }
-            },
-            confirmEdit() {
-                let evaluationInfo = this.evaluationList[this.curEvaIndex]
-                evaluationInfo.testPaper = this.examPaperList
-                this.$router.push({
-                    name: 'createEvaluation',
-                    params: {
-                        evaluationInfo
-                    }
-                })
-            },
-            editEvaluation() {
-                this.$Message.warning('暂未处理编辑评测功能!')
-                //if (this.evaluationList.length > 0) {
-                //    this.editEvaluationStatus = true
-                //}
-            },
-            selectSubject(index) {
-                this.curSubIndex = index
-            },
-            selectBar(index) {
-                this.curBarIndex = index
-                //if (index == 0) {
-                //    this.selectEvaluation(this.curEvaIndex)
-                //}
-            },
-            dateFormat(timestamp) {
-                var date = new Date(timestamp)
-                var Y = date.getFullYear() + '-'
-                var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-'
-                var D = date.getDate() + ' '
-                return Y + M + D;
-            },
-            
-            //查询评测列表
-            findEvaluation() {
-                let requestData = {
-                    code: this.scope == 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId
+            } else {
+                this.$Message.warning("此账号暂未加入任何学校!")
+            }
+        },
+        confirmEdit() {
+            let evaluationInfo = this.evaluationList[this.curEvaIndex]
+            evaluationInfo.testPaper = this.examDetaiInfo
+            this.$router.push({
+                name: 'createEvaluation',
+                params: {
+                    evaluationInfo
                 }
-                this.$api.learnActivity.FindExamInfo(requestData).then(
-                    res => {
-                        if (res.error == null) {
-                            this.evaluationList = res.examInfo
-                            this.filterByPeriod()
-                            //如果当前学段没有评测则自动切换下一个学段
-                            if (!this.evaListShow.length) {
-                                if (this.schoolBase.period && this.schoolBase.period.length > 1) {
-                                    this.filterPeriod = this.schoolBase.period[1].id
-                                    this.filterByPeriod()
-                                }
+            })
+        },
+        editEvaluation() {
+            this.$Message.warning('暂未处理编辑评测功能!')
+        },
+        selectSubject(index) {
+            this.curSubIndex = index
+        },
+        selectBar(index) {
+            this.curBarIndex = index
+        },
+        dateFormat(timestamp) {
+            var date = new Date(timestamp)
+            var Y = date.getFullYear() + '-'
+            var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-'
+            var D = date.getDate() + ' '
+            return Y + M + D;
+        },
+
+        //查询评测列表
+        findEvaluation() {
+            let requestData = {
+                code: this.scope == 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId
+            }
+            this.$api.learnActivity.FindExamInfo(requestData).then(
+                res => {
+                    if (res.error == null) {
+                        res.examInfo = res.examInfo.sort((a, b) => {
+                            return a.createTime - b.createTime > 0 ? -1 : 1
+                        })
+                        this.evaluationList = res.examInfo
+                        this.filterByPeriod()
+                        //如果当前学段没有评测则自动切换下一个学段
+                        if (!this.evaListShow.length) {
+                            if (this.schoolBase.period && this.schoolBase.period.length > 1) {
+                                this.filterPeriod = this.schoolBase.period[1].id
+                                this.filterByPeriod()
                             }
-                        } else {
-                            this$Message.error('API ERROR!')
                         }
+                    } else {
+                        this$Message.error('API ERROR!')
                     }
-                )
-            },
-            //根据学段筛选评测
-            filterByPeriod() {
-                this.curEvaIndex = 0
-                if (this.filterPeriod) {
-                    this.evaListShow = this.evaluationList.filter(item => item.period.id === this.filterPeriod)
-                } else {
-                    this.evaListShow = [...this.evaluationList]
                 }
+            )
+        },
+        //根据学段筛选评测
+        filterByPeriod() {
+            this.curEvaIndex = 0
+            if (this.filterPeriod) {
+                this.evaListShow = this.evaluationList.filter(item => item.period.id === this.filterPeriod)
+            } else {
+                this.evaListShow = [...this.evaluationList]
+            }
+            if (this.evaListShow.length) {
                 this.selectEvaluation(0)
-            },
-            selectEvaluation(index) {
-                this.curSubIndex = 0
-                this.curEvaIndex = index
-                if (this.evaListShow[this.curEvaIndex] && this.evaListShow[this.curEvaIndex].papers == 0) {
-                    this.findExamPaper()
-                } else {
-                    this.examPaperList = this.evaListShow[this.curEvaIndex]
-                }
-            },
-            
-            findExamPaper() {
-                let requestData = {
-                    id: this.evaListShow[this.curEvaIndex].id,
-                    code: this.evaListShow[this.curEvaIndex].code
-                }
-                this.isLoading = true
-                this.$api.learnActivity.FindExamInfos(requestData).then(
-                    async res => {
-                        if (!res.error) {
-                            let resData = res.examInfo[0]
-                            let dataInfo = this._.cloneDeep(res.examInfo[0])
-                            resData.papers.forEach(async (item, index) => {
-                                resData.papers[index] = await this.$evTools.getFullPaper(item)
-                            })
-                            this.evaListShow.splice(this.curEvaIndex, 1, resData)
+            }
 
-                            //方便查看数据结构,暂时使用
-                            
-                            //this.examPaperList = {}
-                            //for (let i = 0; i < dataInfo.papers.length; i++) {
-                            //    let resData = {}
-                            //    resData.period = dataInfo.period.name
-                            //    resData.subjectName = dataInfo.subjects[i].name
-                            //    resData.class = dataInfo.targetClassIds
-                            //    resData.code = dataInfo.code
-                            //    resData.id = dataInfo.id
-                            //    resData.grade = dataInfo.grades
-                            //    resData.papers = await this.$evTools.getFullPaper(dataInfo.papers[i])
-                            //    this.examPaperList.push(resData)
-                            //}
-                            for (let i = 0; i < dataInfo.papers.length; i++) {
-                                dataInfo.papers[i] = await this.$evTools.getFullPaper(dataInfo.papers[i])
-                            }
-                            console.log('dataInfo',dataInfo)
-                            this.examPaperList = dataInfo
-                        } else {
-                            this.$Message.error('API ERROR!')
-                        }
-                    },
-                    err => {
-                        this.$Message.error('API ERROR!')
-                    }
-                ).finally(() => {
-                    this.isLoading = false;
-                })
+        },
+        selectEvaluation(index) {
+            this.curSubIndex = 0
+            this.curEvaIndex = index
+            if (this.evaListShow[this.curEvaIndex] && this.evaListShow[this.curEvaIndex].papers == 0) {
+                this.findExamPaper()
+            } else {
+                this.examDetaiInfo = this.evaListShow[this.curEvaIndex]
             }
         },
-        created() {
-            if (this.$route.name == 'privateEvaluation') {
-                this.scope = 'private'
-            } else if (this.$route.name == 'schoolEvaluation') {
-                this.scope = 'school'
+        //查询当前评测的试卷信息
+        findExamPaper() {
+            let requestData = {
+                id: this.evaListShow[this.curEvaIndex].id,
+                code: this.evaListShow[this.curEvaIndex].code
             }
-            this.$store.dispatch('user/getSchoolProfile').then(
-                (res) => {
-                    if (res) {
-                        this.schoolBase = res.school_base
-                        // 預設搜尋給第一個
-                        if (res.school_base.period && res.school_base.period.length) {
-                            this.filterPeriod = res.school_base.period[0].id
+            this.isLoading = true
+            this.$api.learnActivity.FindExamInfos(requestData).then(
+                async res => {
+                    if (!res.error) {
+                        let resData = res.examInfo[0]
+                        for (let index in resData.papers) {
+                            resData.papers[index] = await this.$evTools.getFullPaper(resData.papers[index])
                         }
+                        // let dataInfo = this._.cloneDeep(resData)
+                        this.evaListShow.splice(this.curEvaIndex, 1, resData)
+                        // for (let i = 0; i < dataInfo.papers.length; i++) {
+                        //     dataInfo.papers[i] = await this.$evTools.getFullPaper(dataInfo.papers[i])
+                        // }
+                        // this.examDetaiInfo = dataInfo
+                        this.examDetaiInfo = resData
+                    } else {
+                        this.$Message.error('API ERROR!')
                     }
+                },
+                err => {
+                    this.$Message.error('API ERROR!')
                 }
             ).finally(() => {
-                this.findEvaluation()
+                this.isLoading = false;
             })
-        },
-        watch: {
-            $route: {
-                handler: function (to, from) {
-                    if (this.$route.name == 'privateEvaluation') {
-                        this.scope = 'private'
-                    } else if (this.$route.name == 'schoolEvaluation'){
-                        this.scope = 'school'
+        }
+    },
+    created() {
+        if (this.$route.name == 'privateEvaluation') {
+            this.scope = 'private'
+        } else if (this.$route.name == 'schoolEvaluation') {
+            this.scope = 'school'
+        }
+        this.$store.dispatch('user/getSchoolProfile').then(
+            (res) => {
+                if (res) {
+                    this.schoolBase = res.school_base
+                    // 預設搜尋給第一個
+                    if (res.school_base.period && res.school_base.period.length) {
+                        this.filterPeriod = res.school_base.period[0].id
                     }
-                },
-                immediate: true
+                }
             }
-        },
-        computed: {
-            filterPeriodName: function () {
-                let pId = this.filterPeriod
-                let name = ''
-                if (pId) {
-                    let temp = this.$store.state.user.schoolProfile.school_base.period.filter(item => {
-                        return pId == item.id
-                    })
-                    if (temp.length > 0) name = temp[0].name
+        ).finally(() => {
+            this.findEvaluation()
+        })
+    },
+    watch: {
+        $route: {
+            handler: function (to, from) {
+                if (this.$route.name == 'privateEvaluation') {
+                    this.scope = 'private'
+                } else if (this.$route.name == 'schoolEvaluation') {
+                    this.scope = 'school'
                 }
-                return name
             },
+            immediate: true
         }
+    },
+    computed: {
+        filterPeriodName: function () {
+            let pId = this.filterPeriod
+            let name = ''
+            if (pId) {
+                let temp = this.$store.state.user.schoolProfile.school_base.period.filter(item => {
+                    return pId == item.id
+                })
+                if (temp.length > 0) name = temp[0].name
+            }
+            return name
+        },
     }
+}
 </script>
 <style lang="less" scoped>
-    @import "./ManageEvaluation.less";
+@import "./ManageEvaluation.less";
 </style>
 <style lang="less">
-    .evalustion-base-attr .ivu-form .ivu-form-item-label {
-        color: #a5a5a5;
-    }
-    .evaluation-attr-form .ivu-select-disabled .ivu-select-selection {
-        background: none;
-    }
-    .sort-dropdown{
-    .title{
+.evalustion-base-attr .ivu-form .ivu-form-item-label {
+    color: #a5a5a5;
+}
+.evaluation-attr-form .ivu-select-disabled .ivu-select-selection {
+    background: none;
+}
+.sort-dropdown {
+    .title {
         color: white;
         font-size: 14px;
     }
-    .ivu-select-dropdown{
+    .ivu-select-dropdown {
         background-color: #2d2d2d;
         border-radius: 2px;
         border: 1px #464646 solid;
-        .ivu-dropdown-menu{
+        .ivu-dropdown-menu {
             li {
                 color: #ccc;
-                font-size: 12px!important;
-                &:hover{
+                font-size: 12px !important;
+                &:hover {
                     color: #2d2d2d;
                 }
             }

+ 8 - 2
TEAMModelOS/ClientApp/src/view/learnactivity/ManualCreate.vue

@@ -103,7 +103,7 @@
             </div>
             <div class="question-list-wrap">
                 <!-- <Loading :top="100" v-show="isLoading"></Loading> -->
-                <ExerciseList :selQue="selQue" :propsList="questionList" @pageScroll="doScroll"
+                <ExerciseList ref="exList" :selQue="selQue" :propsList="questionList" @pageScroll="doScroll"
 				 @on-question-change="selectQuestion"></ExerciseList>
                 <EmptyData style="margin-top:120px;" v-if="!isLoading && questionList.length == 0" textContent="没有查询到题目"></EmptyData>
                 <!-- <div class="page-wrap">
@@ -269,7 +269,7 @@
                     "type": this.deleteAll(this.manualFilter.type),
                     "field": [],
                     "scope": scope,
-                    "pId": ""
+                    "pid": null
                 }
                 return new Promise((resolve, reject) => {
                     this.$api.newEvaluation.FindExerciseList(queryData).then(res => {
@@ -375,7 +375,13 @@
 			
 			this.$EventBus.$off('onPaperItemChange')
 		    this.$EventBus.$on('onPaperItemChange', data => {
+				console.log('eventBus', data)
 		        this.shoppingQuestionList = JSON.parse(JSON.stringify(data))
+				this.$nextTick(() => {
+					if(this.$refs.exList){
+						this.$refs.exList.selectList = JSON.parse(JSON.stringify(data))
+					}
+				})
 		        let groupResult = this.$jsFn.groupBy(data, 'type')
 		        this.groupList = { ...this.groupQuestion }
 		        for (let i = 0; i < groupResult.length; i++) {

+ 87 - 4
TEAMModelOS/ClientApp/src/view/learnactivity/PaperScore.less

@@ -41,7 +41,9 @@
             display: block;
         }
     }
-    
+    .fast-score-tag{
+        display: inline-block;
+    }
 }
 .exercise-item .compose-box .child-item:hover {
     .qu-info-box{
@@ -50,6 +52,9 @@
             display: block;
         }
     }
+    .fast-score-tag{
+        display: inline-block;
+    }
     
 }
 .scoring-input-box:hover  .qu-info-box {
@@ -57,6 +62,7 @@
     .mark-btn-box{
         display: block;
     }
+    
 }
 .scoring-exercise-wrap .stu-answer-box{
     padding: 10px 10px 10px 5px;
@@ -221,14 +227,14 @@
     }
     .score-input{
         width: 60px; 
-        margin-right:10px;
+        margin: auto;
 
     }
 
 	.compose-box{
 		.child-item{
 			position: relative;
-			margin:20px 10px 0 10px;
+			margin-top:20px;
 			display: flex;
 			&-question{
 				font-size: 14px;
@@ -265,4 +271,81 @@
 				}
 			}
 		}
-	}
+    }
+    .qu-order-tag{
+        display: inline-block;
+        height: 18px;
+        border-radius: 4px;
+        background-color: #1cc0f3;
+        color: white;
+        cursor: pointer;
+        margin-right: 5px;
+        line-height: 16px;
+        text-align: center;
+        font-size: 12px;
+        padding: 2px 6px;
+    }
+    .qu-order-tag-def{
+        display: inline-block;
+        width: 24px;
+        height: 24px;
+        border-radius: 50%;
+        background-color: #e5e5e5;
+        color: black;
+        cursor: pointer;
+        margin-right: 5px;
+        line-height: 24px;
+        text-align: center;
+        font-size: 12px;
+    }
+    .fast-score-tag{
+        background: #19be6b;
+        color: white;
+        width: 20px;
+        height: 18px;
+        border-radius: 4px;
+        font-size: 12px;
+        display: none; 
+        line-height: 18px;
+    }
+    .stu-status-tag{
+        background: #ed4014;
+        font-size: 12px;
+        padding: 3px 8px;
+        font-weight: 800;
+        border-radius: 4px;
+        color: white;
+    }
+    .complete-score-box{
+        width: 100%;
+        text-align: center;
+    }
+    .complete-icon{
+        display: block;
+        color: #19be6b;
+        font-size: 150px;
+        margin: auto;
+        margin-top:50px;
+    }
+    .complete-text{
+        display: block;
+        font-size: 18px;
+        margin: auto;
+        // margin-top:10px;
+    }
+    .complete-stu-info{
+        font-size: 24px;
+        // text-align: left;
+        margin: auto;
+        margin-top: 0px;
+    }
+
+    .complete-next{
+        user-select: none;
+        margin-top: 10px;
+        text-decoration: underline;
+        cursor: pointer;
+        &:hover{
+            color: #0086E6;
+        }
+    }

+ 168 - 82
TEAMModelOS/ClientApp/src/view/learnactivity/PaperScore.vue

@@ -3,12 +3,24 @@
         <!-- 题目列表部分 -->
         <Loading :top="200" type="1" style="text-align:center" v-if="dataLoading"></Loading>
         <div class="scoring-paper-header">
-            <span class="base-info-item">学生姓名:<span class="analysis-info">{{studentAnswer.name}}</span></span>
-            <span class="base-info-item">总分:<span class="analysis-info">{{scoreTotal}}</span></span>
-            <span class="base-info-item">已评:<span class="analysis-info">{{scoreTotal}}</span></span>
-            <span class="base-info-item">未评:<span class="analysis-info">{{scoreTotal}}</span></span>
-
-            <span class="base-info-btn" type="success" @click="savePaper">
+            <span class="base-info-item">
+                学生姓名:
+                <span class="analysis-info">{{studentAnswer.name}}</span>
+                <!-- <span class="stu-status-tag">未作答</span> -->
+            </span>
+            <span class="base-info-item">总分:<span class="analysis-info">{{scoreTotal}}分</span></span>
+            <div style="display:inline-block;" v-if="studentAnswer.scores">
+                <span class="base-info-item">题号:</span>
+                <span @click="goToQuestion(index)" v-for="(groupItem,groupIndex) in paperInfo.item" :key="groupIndex">
+                    <span :class="studentAnswer.scores[groupIndex] >= 0 ? 'qu-order-tag':'qu-order-tag-def'" v-if="!groupItem.children.length" @click="goToQuestion(groupIndex)">
+                        {{(groupIndex + 1)}}
+                    </span>
+                    <span @click="goToQuestion(groupIndex + index)" v-for="(item,index) in groupItem.children" :key="index" :class="studentAnswer.scores[groupIndex + index] >= 0 ? 'qu-order-tag':'qu-order-tag-def'">
+                        {{(groupIndex + 1) + '-' + (index + 1)}}
+                    </span>
+                </span>
+            </div>
+            <span class="base-info-btn" type="success" @click="saveScore">
                 <Icon type="ios-albums-outline" />
                 保存打分
             </span>
@@ -25,7 +37,7 @@
                 {{ showQu ? '隐藏题干' : '显示题干'}}
             </span>
         </div>
-        <vuescroll ref="que">
+        <vuescroll ref="question-scrool" v-show="!isComplete">
             <div class="qu-list-wrap scoring-exercise-wrap" ref="mathJaxContainer" v-if="!dataLoading">
                 <div class="list-view" :key="'group'+ typeIndex" v-for="(typeItem,typeIndex) in groupList">
                     <p class="type-name">
@@ -35,9 +47,27 @@
                     </p>
                     <div ref="ques" v-for="(item,index) of typeItem.list" :key="'qu'+ index" :class='["exercise-item",isError(item.id) ? "exercise-item-error":""]'>
                         <!-- 非综合题-->
-                        <div v-if="item.type != 'compose'" style="display:flex;width:100%;" class="not-compose-box">
-                            <div class="scoring-input-box" @click.stop v-if="studentAnswer.scores && studentAnswer.scores.length" v-model="studentAnswer.scores[typeIndex + index]">
-                                <InputNumber size="small" :formatter="value => value < 0 ? 0 : value" :min="0" :max="10" placeholder="0" class="score-input" />
+                        <div v-if="item.type != 'compose'" style="display:flex;width:100%;" class="not-compose-box" :id="'qustion'+ (typeIndex + index)">
+                            <div class="scoring-input-box" @click.stop v-if="studentAnswer.scores && studentAnswer.scores.length">
+                                <InputNumber v-model="studentAnswer.scores[typeIndex + index]" size="small" :formatter="value => value < 0 ? '' : `${value}分`" :parser="value => value.replace('分', '')" :min="0" :max="item.score" placeholder="0分" class="score-input" />
+                                <div style="display:flex;justify-content: space-evenly;margin-top:5px;">
+                                    <span class="fast-score-tag" title="满分" @click="fastSetScore((typeIndex + index),item.score)">
+                                        <!-- 题目分数 -->{{item.score}}
+                                    </span>
+                                    <span class="fast-score-tag" title="零分" @click="fastSetScore((typeIndex + index),0)">
+                                        0
+                                    </span>
+                                </div>
+                                <div style="display:flex;justify-content: space-evenly;margin-top:5px;" v-show="showQu">
+                                    <span class="fast-score-tag" title="上一题" :style="{'background':'#aeaeae','cursor':(typeIndex + index) == 0 ? 'not-allowed':''}" @click="goToQuestion((typeIndex + index) - 1)">
+                                        <!-- 上一题-->
+                                        <Icon type="md-arrow-round-back" />
+                                    </span>
+                                    <span class="fast-score-tag" title="下一题" :style="{'background':'#aeaeae','cursor':(typeIndex + index + 1) == studentAnswer.scores.legnth ? 'not-allowed':''}" @click="goToQuestion((typeIndex + index) + 1)">
+                                        <!-- 下一题 -->
+                                        <Icon type="md-arrow-round-forward" />
+                                    </span>
+                                </div>
                             </div>
                             <div class="qu-info-box">
                                 <!-- 题干部分 -->
@@ -57,6 +87,9 @@
                                     <p class="answer-title">
                                         <span v-show="!showQu" class="item-question-order">题号 {{ index + 1 }} .</span>
                                         【学 生 作 答】
+                                        <Icon type="md-checkmark" v-if="studentAnswer.scores[typeIndex + index] == item.score" />
+                                        <Icon type="md-close" color="#ed4014" v-else-if="studentAnswer.scores[typeIndex + index] == 0" />
+                                        <Icon custom="iconfont icon-half-right" color="#ff9900" v-else-if="studentAnswer.scores[typeIndex + index] != -1" />
                                     </p>
                                     <!--学生作答答案显示区域-->
                                     <div class="stu-answer-box item-explain-details" v-if="studentAnswer.answers && studentAnswer.answers.length">
@@ -65,27 +98,18 @@
                                             <Icon type="md-create" />
                                             <span style="margin-left:5px;">批注</span>
                                         </div>
-                                        <!-- <BaseMyCanvas></BaseMyCanvas> -->
-                                        <!--问答题答案-->
-                                        <div v-if="item.type === 'subjective'" :id="'answer'+ (typeIndex + index)">
-                                            <div v-for="(answerItem,answerIndex) in studentAnswer.answers[typeIndex + index]" :key="'an'+ answerIndex">
-                                                <span v-html="(answerItem && answerItem.length) > 0 ? answerItem : '暂未作答'"></span><br />
-                                            </div>
-                                        </div>
                                         <!--填空题答案-->
-                                        <div v-else-if="item.type === 'complete'" :id="'answer'+ (typeIndex + index)">
+                                        <div v-if="item.type === 'complete'" :id="'answer'+ (typeIndex + index)">
                                             <div v-for="(answerItem,answerIndex) in studentAnswer.answers[typeIndex + index]" :key="'an'+ index">
-                                                <div :class="[ item.type === 'complete' ? 'item-answer-items':'']">
+                                                <div class="item-answer-items">
                                                     <p style="margin-bottom:5px;">{{answerIndex+1}}、<span v-html="answerItem" style="display:inline-block;"></span></p>
                                                 </div>
                                             </div>
                                         </div>
                                         <!--其余题型答案-->
                                         <div v-else :id="'answer'+ (typeIndex + index)">
-                                            <div style="display:flex;margin-left:5px">
-                                                <span style="margin-left:5px" v-for="(answerItem,answerIndex) in studentAnswer.answers[typeIndex + index]" :key="index">
-                                                    {{answerItem.length > 0 ? answerItem : "暂未作答"}}
-                                                </span>
+                                            <div>
+                                                <span v-html="studentAnswer.answers[typeIndex + index]"></span><br />
                                             </div>
                                         </div>
                                     </div>
@@ -137,16 +161,33 @@
                                 </transition>
                             </div>
                         </div>
-
                         <!-- 综合题 -->
                         <div v-else style="width:100%;" class="compose-box">
                             <div class="item-question" style="margin-left:90px; margin-bottom:10px;" v-show="showQu">
                                 <div class="item-question-order">{{ index + 1 }} .</div>
                                 <div class="item-question-text" v-html="item.question"></div>
                             </div>
-                            <div class="child-item" v-for="(childItem,childIndex) in item.children" :key="childIndex">
-                                <div class="scoring-input-box" @click.stop v-if="item.type == 'compose' && studentAnswer.scores && studentAnswer.scores.length" v-model="studentAnswer.scores[typeIndex + index + childIndex]">
-                                    <InputNumber size="small" :formatter="value => value < 0 ? 0 : value" :min="0" :max="10" placeholder="0" class="score-input" />
+                            <div class="child-item" v-for="(childItem,childIndex) in item.children" :key="childIndex" :id="'qustion'+(typeIndex + index + childIndex)">
+                                <div class="scoring-input-box" @click.stop v-if="item.type == 'compose' && studentAnswer.scores && studentAnswer.scores.length">
+                                    <InputNumber v-model="studentAnswer.scores[typeIndex + index + childIndex]" size="small" :formatter="value => value < 0 ? '' : `${value}分`" :parser="value => value.replace('分', '')" :min="0" :max="childItem.score" placeholder="0分" class="score-input" />
+                                    <div style="display:flex;justify-content: space-evenly;margin-top:5px;">
+                                        <span class="fast-score-tag" title="满分" @click="fastSetScore((typeIndex + index + childIndex),childItem.score)">
+                                            <!-- 题目分数 -->{{childItem.score}}
+                                        </span>
+                                        <span class="fast-score-tag" title="零分" @click="fastSetScore((typeIndex + index + childIndex),0)">
+                                            0
+                                        </span>
+                                    </div>
+                                    <div style="display:flex;justify-content: space-evenly;margin-top:5px;" v-show="showQu">
+                                        <span class="fast-score-tag" title="上一题" :style="{'background':'#aeaeae','cursor':(typeIndex + index + childIndex) == 0 ? 'not-allowed':''}" @click="goToQuestion((typeIndex + index + childIndex) - 1)">
+                                            <!-- 上一题-->
+                                            <Icon type="md-arrow-round-back" />
+                                        </span>
+                                        <span class="fast-score-tag" title="下一题" :style="{'background':'#aeaeae','cursor':(typeIndex + index + childIndex + 1) == studentAnswer.scores.length ? 'not-allowed':''}" @click="goToQuestion((typeIndex + index + childIndex) + 1)">
+                                            <!-- 下一题 -->
+                                            <Icon type="md-arrow-round-forward" />
+                                        </span>
+                                    </div>
                                 </div>
                                 <div class="qu-info-box">
                                     <div class="child-item-question" v-show="showQu">
@@ -162,8 +203,11 @@
                                     </div>
                                     <div class="stu-answer-detail">
                                         <p class="answer-title">
-                                            <span class="child-item-question-order" v-show="!showQu">{{ index + 1 }} .【小题{{ childIndex + 1 }}】</span>
+                                            <span class="child-item-question-order" v-show="!showQu">【题号 {{(index + 1)+'-'+ (childIndex + 1) }}】</span>
                                             【学 生 作 答】
+                                            <Icon type="md-checkmark" v-if="studentAnswer.scores[typeIndex + index + childIndex] == childItem.score" />
+                                            <Icon type="md-close" color="#ed4014" v-else-if="studentAnswer.scores[typeIndex + index + childIndex] == 0" />
+                                            <Icon custom="iconfont icon-half-right" color="#ff9900" v-else-if="studentAnswer.scores[typeIndex + index + childIndex] != -1" />
                                         </p>
                                         <!--学生作答答案显示区域-->
                                         <div class="stu-answer-box item-explain-details" v-if="studentAnswer.answers && studentAnswer.answers.length">
@@ -172,15 +216,8 @@
                                                 <Icon type="md-create" />
                                                 <span style="margin-left:5px;">批注</span>
                                             </div>
-                                            <!-- <BaseMyCanvas></BaseMyCanvas> -->
-                                            <!--问答题答案-->
-                                            <div v-if="item.type === 'subjective'" :id="'answer'+ (typeIndex + index)">
-                                                <div v-for="(answerItem,answerIndex) in studentAnswer.answers[typeIndex + index + childIndex]" :key="'an'+ answerIndex">
-                                                    <span v-html="(answerItem && answerItem.length) > 0 ? answerItem : '暂未作答'"></span><br />
-                                                </div>
-                                            </div>
                                             <!--填空题答案-->
-                                            <div v-else-if="item.type === 'complete'" :id="'answer'+ (typeIndex + index)">
+                                            <div v-if="item.type === 'complete'" :id="'answer'+ (typeIndex + index)">
                                                 <div v-for="(answerItem,answerIndex) in studentAnswer.answers[typeIndex + index + childIndex]" :key="'an'+ index">
                                                     <div :class="[ item.type === 'complete' ? 'item-answer-items':'']">
                                                         <p style="margin-bottom:5px;">{{answerIndex+1}}、<span v-html="answerItem" style="display:inline-block;"></span></p>
@@ -189,8 +226,8 @@
                                             </div>
                                             <!--其余题型答案-->
                                             <div v-else :id="'answer'+ (typeIndex + index)">
-                                                <div v-for="(answerItem,answerIndex) in studentAnswer.answers[typeIndex + index + childIndex]" :key="'an'+ answerIndex">
-                                                    <span v-html="(answerItem && answerItem.length) > 0 ? answerItem : '暂未作答'"></span><br />
+                                                <div>
+                                                    <span v-html="studentAnswer.answers[typeIndex + index]"></span><br />
                                                 </div>
                                             </div>
                                         </div>
@@ -200,17 +237,13 @@
                                         <span class="explain-title">【答ㅤ案】</span>
                                         <div class="item-explain-details">
                                             <!-- 问答题答案 -->
-                                            <div v-if="item.type === 'subjective'">
+                                            <div v-if="item.type === 'subjective' || item.type === 'complete'">
                                                 <span v-for="(answer,index) in childItem.answer" :key="index" v-html="childItem.answer.length ? answer : '未设置答案'"></span>
                                             </div>
                                             <!-- 问答题答案 -->
                                             <div v-else-if="item.type === 'judge'">
                                                 <span>{{ childItem.answer.length ? (childItem.answer[0] === 'A' ? '正确' : '错误') : '未设置答案' }}</span>
                                             </div>
-                                            <!-- 填空题答案 -->
-                                            <div v-else-if="item.type === 'complete'">
-                                                <span :class="[ childItem.type === 'complete' ? 'item-answer-item':'']" v-for="(answer,index) in childItem.answer" :key="index" v-html="answer"></span>
-                                            </div>
                                             <!-- 其余题型答案 -->
                                             <div v-else>
                                                 <span :class="[ item.type === 'complete' ? 'item-answer-item':'']" v-for="(answer,index) in childItem.answer" :key="index" v-html="answer"></span>
@@ -237,22 +270,31 @@
                                         </div>
                                     </div>
                                 </div>
-
                             </div>
                         </div>
-
                     </div>
                 </div>
             </div>
         </vuescroll>
+        <div v-show="isComplete" class="complete-score-box">
+            <Icon class="complete-icon" type="md-checkmark-circle" />
+            <p class="complete-stu-info">{{studentAnswer.name}} ({{scoreTotal}}分)</p>
+            <p class="complete-next" @click="nextStu">下一位学生>>></p>
+        </div>
     </div>
 </template>
 <script>
 import html2canvas from 'html2canvas';
+import BlobTool from '@/utils/blobTool.js';
 export default {
     components: {
     },
     props: {
+        examId: {
+            type: String,
+            default: '',
+            required: true
+        },
         paper: {
             type: Object,
             default: () => { }
@@ -264,6 +306,7 @@ export default {
     },
     data() {
         return {
+            isComplete: false,
             isAllOpen: true,
             paperInfo: {},
             dataLoading: false,
@@ -280,7 +323,6 @@ export default {
             groupList: [],
             typeList: ['single', 'multiple', 'judge', 'complete', 'subjective', 'compose'],
             errorList: [],
-            scoreTotal: 0,
             showAnswer: false,
             showQu: true,
             showOption: false
@@ -288,6 +330,24 @@ export default {
         }
     },
     methods: {
+        //点评下一位学生
+        nextStu() {
+            // this.isComplete = false
+            this.$emit('nextStu')
+        },
+        //快速定位题目
+        goToQuestion(index) {
+            console.log(index)
+            this.$refs["question-scrool"].scrollIntoView('#qustion' + index, 500)
+
+        },
+        //快速打分
+        fastSetScore(index, score) {
+            console.log(index, score)
+            // this.studentAnswer.scores[index] = score
+            this.$set(this.studentAnswer.scores, index, score)
+            console.log(this.studentAnswer)
+        },
         // 批注学生作答数据
         markStuAnswer(index) {
             this.$Message.warning('暂未处理批注功能!')
@@ -315,40 +375,26 @@ export default {
             context.stroke();
         },
         //保存学生作答信息
-        savePaper() {
-            //if (this.paperInfo.papers.item.length !== 0) {
-            //    let point = []
-            //    let config = 0 //已评审题目数量
-            //    for (let i = 0; i < this.paperInfo.papers.item.length; i++) {
-            //        if (this.paperInfo.papers.item[i].stuScore !== null && Number(this.paperInfo.papers.item[i].stuScore) !== -1) {
-            //            point.push(this.paperInfo.papers.item[i].stuScore)
-            //            config++
-            //        }
-            //    }
-            //    if (config == this.paperInfo.papers.item.length) {
-            //        let requestData = {
-            //            "id": this.paperInfo.id,
-            //            "code": this.paperInfo.code,
-            //            "point": point,
-            //            "studentId": this.studentInfo.id,
-            //            "classId": this.studentInfo.classId,
-            //            "school": this.paperInfo.papers.code,
-            //            "subjectId": this.paperInfo.papers.subjectId
-            //        }
-            //        this.$api.learnActivity.UpsertAllRecord(requestData).then(res => {
-            //            if (res.error == null) {
-            //                this.$Message.success('成绩保存成功!')
-            //                this.$emit('closeTest', '1')
-            //                this.getAllStudentData()
-            //            } else {
-            //                this.$Message.error('成绩保存失败!')
-            //            }
-            //        })
-            //    } else {
-            //        this.$Message.warning('请完善学生评分信息!')
-            //    }
-            //}
-            console.log(this.studentAnswer)
+        saveScore() {
+            let requestData = {
+                "id": this.examId,
+                "code": this.paperInfo.code,
+                "point": this.studentAnswer.scores,
+                "studentId": this.studentAnswer.id,
+                "classId": this.studentAnswer.classId,
+                "school": this.paperInfo.code,
+                "subjectId": this.paperInfo.subjectId
+            }
+            this.$api.learnActivity.UpsertAllRecord(requestData).then(res => {
+                if (res.error == null) {
+                    this.$Message.success('成绩保存成功!')
+                    this.isComplete = true
+                } else {
+                    this.$Message.error('成绩保存失败!')
+                }
+            })
+            console.log('保存打分', this.studentAnswer)
+            console.log('试卷信息', this.paperInfo)
         },
         openAnswer() {
             this.$refs.exPaper.onHandleToggles(this.isAllOpen)
@@ -400,6 +446,7 @@ export default {
         paper: {
             handler(newValue, oldValue) {
                 this.paperInfo = newValue
+                console.log('paperInfo', this.paperInfo)
             },
             deep: true
         },
@@ -428,6 +475,7 @@ export default {
                             })
                         });
                     }
+                    console.log('groupList', this.groupList)
                     this.dataLoading = false
                     this.$nextTick(() => {
                         window.MathJax.Hub.Queue(["Typeset", MathJax.Hub, this.$refs.mathJaxContainer]);
@@ -437,8 +485,31 @@ export default {
             deep: true
         },
         studentAnswer: {
-            handler(newValue, oldValue) {
+            async handler(newValue, oldValue) {
                 console.log('学生作答数据', newValue)
+                if (!this.studentAnswer.status) {
+                    if (newValue.answers.length) {
+                        try {
+                            let a = await this.$tools.getFile(newValue.answers[0] + this.$store.state.schoolSas.sas)
+                            console.log('a', a)
+                            if (a) {
+                                this.$set(this.studentAnswer, 'answers', JSON.parse(a))
+                            } else {
+                                this.$set(this.studentAnswer, 'answers', [])
+                            }
+                            console.log(this.studentAnswer)
+                        } catch (e) {
+                            console.log('error', e)
+                        }
+                    } else {
+                        let a = newValue.scores.map(item => {
+                            return '暂未作答'
+                        })
+                        console.log('a', a)
+                        this.$set(this.studentAnswer, 'answers', a)
+                    }
+                    this.studentAnswer.status = true
+                }
             },
             deep: true
         }
@@ -448,6 +519,18 @@ export default {
             return id => {
                 return this.errorList.length && this.errorList.map(i => i.id).indexOf(id) > -1
             }
+        },
+        scoreTotal() {
+            console.log('score', this.studentAnswer)
+            if (this.studentAnswer && this.studentAnswer.scores) {
+                let s = this.studentAnswer.scores.reduce((prev, cur) => {
+                    cur = cur < 0 ? 0 : cur
+                    return prev + cur
+                }, 0)
+                console.log(s)
+                return s
+            }
+            return 0
         }
     },
 }
@@ -456,6 +539,9 @@ export default {
 <style scoped lang="less">
 @import "./PaperScore.less";
 </style>
-<style scoped lang="less">
+<style lang="less">
+.scoring-input-box .ivu-input-number-handler-wrap {
+    display: none;
+}
 </style>
 

+ 16 - 0
TEAMModelOS/ClientApp/src/view/learnactivity/Scoring.less

@@ -70,3 +70,19 @@
     background:white;
     padding-bottom:15px;
 }
+
+.stu-status-tag{
+    background: #ed4014;
+    font-size: 12px;
+    padding: 3px 8px;
+    font-weight: 800;
+    border-radius: 4px;
+    color: white;
+}
+.select-status-tag{
+    display: inline-block;
+    width: 7px;
+    height: 7px;
+    border-radius: 50%;
+    margin-right: 5px;
+}

+ 106 - 43
TEAMModelOS/ClientApp/src/view/learnactivity/Scoring.vue

@@ -13,9 +13,12 @@
             <Select filterable v-model="chooseClass" class="filter-select" style="width:140px;" @on-change="getClassStudent" size="small">
                 <Option v-for="(item,index) in classList" v-show="item.gradeId == chooseGrade" :value="item.id" :key="index">{{ item.name }}</Option>
             </Select>
-            <span style="margin-left:5px">学生:</span>
-            <Select filterable v-model="chooseStudent.id" label-in-value class="filter-select" style="width:140px;" size="small" clearable @on-change="getStuName">
-                <Option v-for="(item,index) in students" :value="item.id" :key="index">{{ item.name }}</Option>
+            <span style="margin-left:5px" v-show="showTest">学生:</span>
+            <Select filterable v-model="chooseStudent.id" label-in-value class="filter-select" style="width:140px;" size="small" clearable @on-change="setStuInfo" v-show="showTest">
+                <Option v-for="(item,index) in students" :value="item.id" :key="index">
+                    <span class="select-status-tag" :style="{'background':item.status == 1 ? '#ed4014' : item.status == 2 ? '#ff9900' : '#19be6b'}"></span>
+                    {{ item.name }}
+                </Option>
             </Select>
             <span class="common-icon-text" style=" float: right; margin-right: 25px;" @click="showTest = !showTest" icon="md-apps">
                 <Icon :custom="showTest ? 'iconfont icon-table':'iconfont icon-scoring'" style="margin-right:5px;" />
@@ -24,19 +27,26 @@
         </div>
         <div class="scoring-main-wrap dark-iview-table">
             <Table v-show="!showTest" class="score-box" border :columns="tableColumn" :data="studentScore" :loading="tableLoading" :max-height="tableHeight">
-                <template slot-scope="{ row,index }" :slot="'qu'+qIndex" v-for="(item,qIndex) in quLen">
+                <template slot-scope="{ row,index }" :slot="'qu'+qIndex" v-for="(item,qIndex) in quCount">
                     <div :key="'qu'+qIndex">
-                        <Icon @click="getStuScore(row,qIndex)" size="20" style="cursor:pointer;" type="ios-create-outline" v-if="row.data[qIndex] == -1" />
+                        <span style="cursor:pointer;" @click="noAnswer" v-if="row.data[qIndex] == -1 && row.status == 1">- -</span>
+                        <Icon @click="getStuScore(row,qIndex)" size="20" style="cursor:pointer;" type="ios-create-outline" v-else-if="row.data[qIndex] == -1 && row.status !== 1" />
                         <span @click="getStuScore(row,qIndex)" style="cursor:pointer;" v-else>{{row.data[qIndex]}}</span>
                     </div>
                 </template>
                 <template slot-scope="{ row,index }" slot="total">
                     <strong>{{getcount(studentScore[row._index].data)}}</strong>
                 </template>
+                <!-- 1: 未作答 2:未评分 3:已评分 -->
+                <template slot-scope="{ row,index }" slot="status">
+                    <span class="stu-status-tag" :style="{'background':row.status == 1 ? '#ed4014' : row.status == 2 ? '#ff9900' : '#19be6b'}">
+                        {{row.status == 1 ? '未作答' : row.status == 2 ? '未评分' : '已评分'}}
+                    </span>
+                </template>
                 <Loading slot="loading" :top="-50"></Loading>
             </Table>
             <div class="dark-iview-table scoring-handle-box" v-show="showTest">
-                <PaperScore :paper="paperInfo" :studentAnswer="chooseStudent" ref="exPaper" style="color:#515a6e;"> </PaperScore>
+                <PaperScore :examId="examInfo.id" :paper="paperInfo" :studentAnswer="chooseStudent" ref="exPaper" @nextStu="getNextStu" style="color:#515a6e;"> </PaperScore>
                 <Loading :top="200" type="1" style="text-align:center" v-show="dataLoading"></Loading>
             </div>
         </div>
@@ -60,18 +70,17 @@ export default {
         return {
             tableLoading: false,
             tableHeight: 750,
-            isAllOpen: true,
             showTest: false, //是否评分
             studentData: [],
-            studentList: [],
             dataLoading: false,
-            classData: [], //当前班级信息
             chooseGrade: "",
             chooseClass: "",
             chooseSubject: "",
             chooseStudent: {
                 id: "",
                 name: "",
+                scores: [],
+                answers: []
             },
             scoreList: [
                 {
@@ -88,25 +97,58 @@ export default {
                     fixed: "right",
                     width: 100,
                 },
+                {
+                    title: "状态",
+                    slot: "status",
+                    align: "center",
+                    fixed: "right",
+                    width: 100,
+                }
             ],
             tableColumn: [],
             studentScore: [],
-            studentAns: {},
-            quLen: [],
-            selectStudent: {},
-            studentName: "",
-            scoreTotal: 0,
+            quCount: [],
             paperInfo: {},
+            students: []
         };
     },
     methods: {
+        getNextStu() {
+            console.log('批改下一位学生')
+            console.log(this.paperInfo)
+            let flag = false
+            for (let index in this.paperInfo[this.chooseClass].studentScores) {
+                if (this.paperInfo[this.chooseClass].studentScores[index].indexOf(-1) >= 0) {
+                    if (this.paperInfo[this.chooseClass].studentAnswers[index].length) {
+                        flag = true
+                        this.chooseStudent.id = this.paperInfo[this.chooseClass].studentIds[index]
+                        let curStu = students.find(item => {
+                            return item.id == this.chooseStudent.id
+                        })
+                        if (curStu) this.chooseStudent.name = curStu.name
+                        this.chooseStudent.answers = this.paperInfo[this.chooseClass].studentAnswers[index]
+                        this.chooseStudent.scores = this.paperInfo[this.chooseClass].studentScores[index]
+                        this.chooseStudent.classId = this.chooseClass
+                        this.chooseStudent.status = false
+                        break
+                    }
+                }
+            }
+            if(!flag){
+                this.showTest = false
+                this.$Message.warning('已完成所有学生作答的评分!')
+            }
+        },
+        //学生未作答提示
+        noAnswer() {
+            this.$Message.warning('学生尚未作答,无法评分')
+        },
+        //获取当前学科的试卷信息
         getCurPaper() {
-
             let paperInfo = this.examInfo.papers.find((item) => {
                 return item.subjectId == this.chooseSubject;
             });
             this.paperInfo = this._.cloneDeep(paperInfo)
-            console.log("paperInfo", this.paperInfo);
             this.getClassStudent();
         },
         //点击学生题号前往评分页面
@@ -114,14 +156,27 @@ export default {
             this.showTest = true;
             this.chooseStudent.id = data.id;
             this.chooseStudent.name = data.name;
+            this.chooseStudent.classId = this.chooseClass
             let answerIndex = this.paperInfo[this.chooseClass].studentAns.studentIds.indexOf(data.id);
             if (answerIndex >= 0) {
                 this.chooseStudent["scores"] = this.paperInfo[this.chooseClass].studentAns.studentScores[answerIndex];
                 this.chooseStudent["answers"] = this.paperInfo[this.chooseClass].studentAns.studentAnswers[answerIndex];
+                this.chooseStudent["status"] = false;
             }
         },
-        getStuName(data) {
-            if(data) this.chooseStudent.name = data.label;
+        //获取当前学生信息
+        setStuInfo(data) {
+            if (data) {
+                this.chooseStudent.name = data.label;
+                this.chooseStudent.classId = this.chooseClass
+                let answerIndex = this.paperInfo[this.chooseClass].studentAns.studentIds.indexOf(data.value);
+                if (answerIndex >= 0) {
+                    this.chooseStudent["scores"] = this.paperInfo[this.chooseClass].studentAns.studentScores[answerIndex];
+                    this.chooseStudent["answers"] = this.paperInfo[this.chooseClass].studentAns.studentAnswers[answerIndex];
+                    this.chooseStudent["status"] = false;
+                }
+                console.log('chooseStu', this.chooseStudent)
+            }
         },
         //分数求和
         getcount(arr) {
@@ -133,6 +188,7 @@ export default {
                 }
             }, 0);
         },
+        // 获取班级名单
         getClassStudent() {
             this.tableLoading = true
             if (!this.chooseClass) return;
@@ -144,16 +200,19 @@ export default {
             this.$api.schoolSetting.getClassroomStudent(requestData).then((res) => {
                 if (!res.error) {
                     if (!this.paperInfo[this.chooseClass]) {
-                        this.$set(this.paperInfo, this.chooseClass, {});
+                        // this.$set(this.paperInfo, this.chooseClass, {});
+                        this.paperInfo[this.chooseClass] = {}
                     }
                     this.$set(this.paperInfo[this.chooseClass], "students", res.classrooms[0]);
-                    this.getAllStudentData();
+                    // this.students = res.classrooms[0].students
+                    this.getStudentAnswer();
                 } else {
                     this.$Message.error("API ERROR!");
                 }
             });
         },
-        getAllStudentData() {
+
+        getStudentAnswer() {
             this.dataLoading = true;
             let requestData = {
                 id: this.examInfo.id,
@@ -182,11 +241,10 @@ export default {
             if (this.paperInfo[this.chooseClass]) {
                 let studentData = this.paperInfo[this.chooseClass]["students"];
                 let studentAns = this.paperInfo[this.chooseClass]["studentAns"];
-
                 this.studentScore = [];
                 this.tableColumn = [...this.scoreList];
-                this.quLen = studentAns.studentAnswers[0];
-                for (let i = 0; i < studentAns.studentAnswers[0].length; i++) {
+                this.quCount = studentAns.studentScores[0].length;
+                for (let i = 0; i < this.quCount; i++) {
                     let data = {
                         title: "Q" + (i + 1),
                         slot: "qu" + i,
@@ -195,22 +253,27 @@ export default {
                     };
                     this.tableColumn.push(data);
                 }
-                console.log('column', this.tableColumn)
                 let ans = [];
                 for (let i = 0; i < studentAns.studentIds.length; i++) {
                     for (let k = 0; k < studentData.students.length; k++) {
                         let score = {};
-                        if (
-                            studentAns.studentIds[i] ==
-                            studentData.students[k].id
-                        ) {
+                        if (studentAns.studentIds[i] == studentData.students[k].id) {
                             score.name = studentData.students[k].name;
                             score.id = studentAns.studentIds[i];
                             score.data = studentAns.studentScores[i];
+                            if (studentAns.studentAnswers[i].length == 0) {//学生未作答
+                                score.status = 1
+                            } else if (studentAns.studentScores[i].indexOf(-1) >= 0) {//已作答,未评分
+                                score.status = 2
+                            } else {//已批改
+                                score.status = 3
+                            }
                             this.studentScore.push(score);
                         }
                     }
                 }
+                console.log('表格数据', this.studentScore)
+                this.students = this._.cloneDeep(this.studentScore)
                 if (ans.length) {
                     for (
                         let k = 0;
@@ -244,7 +307,6 @@ export default {
         getStudentInfo(data, index) {
             this.dataLoading = true;
             if (this.studentInfo !== undefined) {
-                this.studentName = this.studentInfo.name;
                 let filData = "";
                 filData = this.studentInfo.id;
                 let ans = [];
@@ -296,9 +358,9 @@ export default {
                 if (n.grades && n.grades.length) {
                     this.chooseGrade = n.grades[0].id;
                 }
-                if (n.targetClassIds && n.targetClassIds.length) {
-                    this.chooseClass = n.targetClassIds[0];
-                }
+                // if (n.targetClassIds && n.targetClassIds.length) {
+                //     this.chooseClass = n.targetClassIds[0];
+                // }
                 if (n.papers && n.papers.length) {
                     let res = n.papers.find((item) => {
                         return item.subjectId == this.chooseSubject;
@@ -307,7 +369,7 @@ export default {
                 } else {
                     this.paperInfo = {};
                 }
-                this.getClassStudent();
+                // this.getClassStudent();
             },
             deep: true,
         },
@@ -322,13 +384,14 @@ export default {
         }
     },
     computed: {
-        students() {
-            if (this.paperInfo && this.paperInfo[this.chooseClass] && this.paperInfo[this.chooseClass]["students"]) {
-                return this.paperInfo[this.chooseClass]["students"].students;
-            } else {
-                return [];
-            }
-        },
+        // students() {
+        //     console.log('获取学生名单', this.paperInfo)
+        //     if (this.paperInfo && this.paperInfo[this.chooseClass] && this.paperInfo[this.chooseClass]["students"]) {
+        //         return this.paperInfo[this.chooseClass]["students"].students;
+        //     } else {
+        //         return [];
+        //     }
+        // },
         classList() {
             if (this.examInfo && this.examInfo.targetClassIds) {
                 let classes = this.$store.state.user.schoolProfile.school_classes.filter(
@@ -350,14 +413,14 @@ export default {
 </style>
 <style lang="less">
 .scoring-main-wrap .ivu-table-fixed-body {
-    background: #353535;
+    background: #2B2B2E;
 }
 .scoring-main-wrap .ivu-table-fixed-right::before,
 .scoring-main-wrap .ivu-table-fixed::before {
     display: none;
 }
 .scoring-main-wrap .ivu-table-fixed-header thead tr th {
-    background: #404040;
+    background: #2B2B2E;
     border-color: #606060;
     color: white;
 }

+ 1 - 1
TEAMModelOS/ClientApp/src/view/login/Index.less

@@ -49,7 +49,7 @@
                 }
             }
             .subTitle{
-                font-size: 12px;
+                font-size: 14px;
                 color: #d1d1d3;
                 margin-bottom: 25px;
             }

File diff suppressed because it is too large
+ 698 - 841
TEAMModelOS/ClientApp/src/view/student-account/Index.vue


+ 12 - 1
TEAMModelOS/ClientApp/src/view/teachcontent/index.vue

@@ -639,7 +639,18 @@
                 })
             },
             downloadFile(index) {
-                window.location.href = this.fileListShow[index].url
+				let curFile = this.fileListShow[index].url
+				const downloadRes = async () => {
+				      let response = await fetch(curFile); // 内容转变成blob地址
+				      let blob = await response.blob();  // 创建隐藏的可下载链接
+				      let objectUrl = window.URL.createObjectURL(blob);
+				      let a = document.createElement('a');
+				      a.href = objectUrl;
+				      a.download = this.fileListShow[index].name;
+				      a.click()
+				      a.remove(); 
+				   }
+				  downloadRes();
             },
             openPreviewFile(index) {
                 this.previewFile = this._.cloneDeep(this.fileListShow[index])

+ 2 - 2
TEAMModelOS/ClientApp/src/view/teachermgmt/components/userList/Index.vue

@@ -225,7 +225,7 @@
             <div class="userListContent">
                 <Table class="scrollstyle" :height="tableHeight" ref="selection" :columns="tableColumns" :data="tableData" @on-selection-change="setTeachers" @on-sort-change="changeSort">
                     <template slot-scope="{ row }" slot="picture">
-                        <PersonalPhoto :name="row.name" :picture="row.picture" :color="row.nameColor"/>
+                        <PersonalPhoto :name="row.name" :picture="row.picture" />
                     </template>
                     <template slot-scope="{ row }" slot="action">
                         <icon icon="shield-alt" style="font-size: 14px;color: #fff;margin-right: 20px;cursor: pointer;" @click="showAuth(row)" />
@@ -252,7 +252,7 @@
                     <tooltip class="userSelected" v-for="(id, key) in ids" :key="key" placement="bottom-start" offset="10">
                         <div slot="content" class="userSelectedTooltip"><span class="userSelectedTooltipName">{{id.name}}</span><br /><span class="userSelectedTooltipContent">{{id.id}}</span></div>
 
-                        <PersonalPhoto :name="id.name" :picture="id.picture" :color="id.nameColor"/>
+                        <PersonalPhoto :name="id.name" :picture="id.picture"/>
                         <!-- <img class="usericon" :src="id.picture" /> -->
                         <span  class="usercontent" v-if="ids.length===1">{{id.name}}</span>
 

+ 3 - 3
TEAMModelOS/Controllers/Common/ExamController.cs

@@ -201,7 +201,7 @@ namespace TEAMModelOS.Controllers
                 //var id = jwt.Payload.Sub;
                 var client = _azureCosmos.GetCosmosClient();
                 List<ExamInfo> examInfo = new List<ExamInfo>();
-                var query = $"select c.id,c.name,c.code,c.period,c.startTime,c.stuCount,c.type,c.progress,c.examType from c ";
+                var query = $"select c.id,c.name,c.code,c.period,c.startTime,c.stuCount,c.type,c.progress,c.examType,c.createTime from c ";
                 await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Exam-{school_code}") }))
                 {
                     using var json = await JsonDocument.ParseAsync(item.ContentStream);
@@ -236,7 +236,7 @@ namespace TEAMModelOS.Controllers
         public async Task<IActionResult> FindSummary(JsonElement requert)
         {
             try
-            {
+            { 
                 //ResponseBuilder builder = ResponseBuilder.custom();
                 //if (!requert.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
                 if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
@@ -766,7 +766,7 @@ namespace TEAMModelOS.Controllers
                         total.Add(result.sum.Where(s => s > 90 && s <= 100).Count());
                     }                   
                 }
-                return Ok(new { papers, subjects,stuScore, total });
+                return Ok(new { papers, subjects,stuScore, stuAns, total });
             }
             catch (Exception ex)
             {

+ 57 - 55
TEAMModelOS/Controllers/Common/VoteController.cs

@@ -31,7 +31,7 @@ namespace TEAMModelOS.Controllers.Learn
     public class VoteController : ControllerBase
     {
         private readonly SnowflakeId _snowflakeId;
-        private readonly AzureCosmosFactory _azureCosmos;       
+        private readonly AzureCosmosFactory _azureCosmos;
         private readonly AzureServiceBusFactory _serviceBus;
 
         public VoteController(AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId)
@@ -75,9 +75,9 @@ namespace TEAMModelOS.Controllers.Learn
             //新增ote
             //string code = request.vote.code;
             var client = _azureCosmos.GetCosmosClient();
-            Vote vote = new Vote();            
+            Vote vote = new Vote();
             request.vote.school = request.vote.code;
-            request.vote.code = request.vote.pk+ "-" + request.vote.code;
+            request.vote.code = request.vote.pk + "-" + request.vote.code;
             request.vote.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
             /*if (request.vote.publishModel.Equals("0"))
             {
@@ -97,8 +97,8 @@ namespace TEAMModelOS.Controllers.Learn
                 request.vote.id = Guid.NewGuid().ToString();
                 //request.survey.status = 100;
                 request.vote.progress = "pending";
-               /* long SequenceNumber = await _serviceBus.GetServiceBusClient().SendLeamMessage<Vote>(Constants.TopicName, request.vote.id, request.vote.code, request.vote.startTime);
-                request.vote.sequenceNumber = SequenceNumber;*/
+                /* long SequenceNumber = await _serviceBus.GetServiceBusClient().SendLeamMessage<Vote>(Constants.TopicName, request.vote.id, request.vote.code, request.vote.startTime);
+                 request.vote.sequenceNumber = SequenceNumber;*/
                 vote = await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(request.vote, new PartitionKey($"{request.vote.code}"));
                 /*if (request.vote.scope.Equals("school"))
                 {
@@ -107,7 +107,7 @@ namespace TEAMModelOS.Controllers.Learn
                 else
                 {
                     vote = await client.GetContainer("TEAMModelOS", "Teacher").CreateItemAsync(request.vote, new PartitionKey($"Vote-{code}"));
-                }*/               
+                }*/
             }
             else
             {
@@ -118,9 +118,9 @@ namespace TEAMModelOS.Controllers.Learn
                 }
                 //request.vote.code = info.code;
                 request.vote.progress = info.progress;
-               /* await _serviceBus.GetServiceBusClient().cancelMessage(Constants.TopicName,info.sequenceNumber);
-                long SequenceNumber = await _serviceBus.GetServiceBusClient().SendLeamMessage<Vote>(Constants.TopicName, request.vote.id, request.vote.code, request.vote.startTime);
-                request.vote.sequenceNumber = SequenceNumber;*/
+                /* await _serviceBus.GetServiceBusClient().cancelMessage(Constants.TopicName,info.sequenceNumber);
+                 long SequenceNumber = await _serviceBus.GetServiceBusClient().SendLeamMessage<Vote>(Constants.TopicName, request.vote.id, request.vote.code, request.vote.startTime);
+                 request.vote.sequenceNumber = SequenceNumber;*/
                 vote = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(request.vote, info.id, new PartitionKey($"{info.code}"));
                 /*if (request.vote.scope.Equals("school"))
                 {
@@ -138,50 +138,50 @@ namespace TEAMModelOS.Controllers.Learn
             //设定结束时间
             //await _serviceBus.GetServiceBusClient().SendLeamMessage<Vote>(Constants.TopicName, request.vote.id, request.vote.code, request.vote.endTime);
             //清除作业
-          /*  if (!request.reset)
-            {
-                //根据作业发布对象查找到每一个具体学生生成关联关系表 HomeWorkStudent
-
-                List<VoteRecord> voteRecords = await _azureCosmos.FindByDict<VoteRecord>(new Dictionary<string, object> { { "id", request.vote.id } });
+            /*  if (!request.reset)
+              {
+                  //根据作业发布对象查找到每一个具体学生生成关联关系表 HomeWorkStudent
+
+                  List<VoteRecord> voteRecords = await _azureCosmos.FindByDict<VoteRecord>(new Dictionary<string, object> { { "id", request.vote.id } });
+
+                  if (voteRecords.IsNotEmpty())
+                  {
+                      await _azureCosmos.DeleteAll(voteRecords);
+                  }*/
+            //List<Target> targets = request.@params.vote.target;
+            //List<VoteRecord> votekStudents = new List<VoteRecord>();
+            //foreach (Target target in targets)
+            //{
+            //    //查询之前是否有 关联关系表 HomeWorkStudent 有则删除
 
-                if (voteRecords.IsNotEmpty())
-                {
-                    await _azureCosmos.DeleteAll(voteRecords);
-                }*/
-                //List<Target> targets = request.@params.vote.target;
-                //List<VoteRecord> votekStudents = new List<VoteRecord>();
-                //foreach (Target target in targets)
-                //{
-                //    //查询之前是否有 关联关系表 HomeWorkStudent 有则删除
-                    
-                //    List<ClassStudent> classroom = await _cosmos.FindByDict<ClassStudent>(new Dictionary<string, object> { { "id", target.classroomCode } });
-                //    if (classroom.IsNotEmpty() && classroom[0].code!=null)
-                //    {
-                //        foreach (ClassStudent student in classroom)
-                //        {
-                //            VoteRecord voteStudent = new VoteRecord();
-                //            voteStudent.id = request.@params.vote.id;
-                //            voteStudent.code = student.code;
-                //            voteStudent.classroom.code = target.classroomCode;
-                //            voteStudent.classroom.name = target.classroomName;
-                //            votekStudents.Add(voteStudent);
-                //        }
-                //    }
-                //}
-                //if (votekStudents.IsNotEmpty())
-                //{
-                //    foreach (VoteRecord voteRecord in votekStudents)
-                //    {
-                //        List<Student> student = await _cosmos.FindByDict<Student>(new Dictionary<string, object> { { "studentId", voteRecord.code } });
-                //        if (student.IsNotEmpty())
-                //        {
-                //            voteRecord.name = student[0].name;
-                //            voteRecord.code = student[0].studentId;
-                //        }
-                //    }
-                //    await _cosmos.SaveOrUpdateAll(votekStudents);
-                //}
-/*            }*/
+            //    List<ClassStudent> classroom = await _cosmos.FindByDict<ClassStudent>(new Dictionary<string, object> { { "id", target.classroomCode } });
+            //    if (classroom.IsNotEmpty() && classroom[0].code!=null)
+            //    {
+            //        foreach (ClassStudent student in classroom)
+            //        {
+            //            VoteRecord voteStudent = new VoteRecord();
+            //            voteStudent.id = request.@params.vote.id;
+            //            voteStudent.code = student.code;
+            //            voteStudent.classroom.code = target.classroomCode;
+            //            voteStudent.classroom.name = target.classroomName;
+            //            votekStudents.Add(voteStudent);
+            //        }
+            //    }
+            //}
+            //if (votekStudents.IsNotEmpty())
+            //{
+            //    foreach (VoteRecord voteRecord in votekStudents)
+            //    {
+            //        List<Student> student = await _cosmos.FindByDict<Student>(new Dictionary<string, object> { { "studentId", voteRecord.code } });
+            //        if (student.IsNotEmpty())
+            //        {
+            //            voteRecord.name = student[0].name;
+            //            voteRecord.code = student[0].studentId;
+            //        }
+            //    }
+            //    await _cosmos.SaveOrUpdateAll(votekStudents);
+            //}
+            /*            }*/
             //return builder.Data(homeWork).build();
             return Ok(new { vote });
         }
@@ -428,9 +428,11 @@ namespace TEAMModelOS.Controllers.Learn
         }
 
 
-        public class Options {
+        public class Options
+        {
 
-            public Options() {
+            public Options()
+            {
                 students = new List<VoteRecord>();
             }
 
@@ -443,7 +445,7 @@ namespace TEAMModelOS.Controllers.Learn
             /// 选项value
             /// </summary>
             public string optionValue { get; set; }
-            
+
             /// <summary>
             /// 选项人
             /// </summary>

+ 11 - 6
TEAMModelOS/Controllers/Item/ItemController.cs

@@ -289,12 +289,17 @@ namespace TEAMModelOS.Controllers
                 {
                     dict.Add("gradeIds[*]", gradeIds);
                 }
-                //if (requert.TryGetProperty("pid",))
-                //{
-                //    dict.Add("pid", pid);
-                //}
-                dict.Add("pid", null);
-                
+                if (requert.TryGetProperty("pid",out JsonElement pd))
+                {
+                    if (pd.ValueKind != JsonValueKind.Null)
+                    {
+                        dict.Add("pid", pd.ToString());
+                    }
+                    else {
+                        dict.Add("pid", null);
+                    }
+                    
+                }
                 AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
                 List<object> items = new List<object>();
                 if (scope.ToString().Equals("private"))

+ 35 - 59
TEAMModelOS/Controllers/School/StudentController.cs

@@ -1893,94 +1893,70 @@ namespace TEAMModelOS.Controllers
                 //參數取得
                 if (!request.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();
                 if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
-                if (!request.TryGetProperty("pw", out JsonElement pw)) return BadRequest();
+                if (!request.TryGetProperty("pw", out JsonElement pw)) return BadRequest();  
 
-                int error = 0;              
-                string auth_token = "";
-                string blob_uri = string.Empty;
-                string blob_sas = string.Empty;
-                dynamic classinfo = new ExpandoObject();
-                bool classExistFlg = false;
-                List<object> courses = new List<object>();
-
-                var response = await client.GetContainer("TEAMModelOS", "Student").ReadItemStreamAsync(id.GetString(), new PartitionKey($"Base-{school_code.ToString().ToLower()}"));
+                var response = await client.GetContainer("TEAMModelOS", "Student").ReadItemStreamAsync(id.GetString(), new PartitionKey($"Base-{school_code.GetString().ToLower()}"));
                 if (response.Status == 200)
                 {
-                    var json = await JsonDocument.ParseAsync(response.ContentStream);
-                    json.RootElement.TryGetProperty("salt", out JsonElement salt);
-                    json.RootElement.TryGetProperty("pw", out JsonElement dbpw);
-                    json.RootElement.TryGetProperty("name", out JsonElement name);
-                    json.RootElement.TryGetProperty("picture", out JsonElement picture); 
+                    var rjson = await JsonDocument.ParseAsync(response.ContentStream);
+                    rjson.RootElement.TryGetProperty("salt", out JsonElement salt);
+                    rjson.RootElement.TryGetProperty("pw", out JsonElement dbpw);
+                    rjson.RootElement.TryGetProperty("name", out JsonElement name);
+                    rjson.RootElement.TryGetProperty("picture", out JsonElement picture);                    
 
                     var HashedPW = Utils.HashedPassword(pw.ToString(), salt.ToString());
-                    if (dbpw.ToString().Equals(HashedPW.ToString()))
+                    if (HashedPW.Equals(dbpw.GetString()))
                     {
-                        //BLOB(學校,唯讀)
-                        string school_code_blob = school_code.GetString().ToLower();
-                        string blobPath = $"{school_code_blob}/student/{id}";
-                        (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(blobPath, BlobContainerSasPermissions.Read);
-                        //所屬班級資訊
+                        string classid = string.Empty;
+                        object classinfo = null;
+                        List<object> courses = new List<object>();
+                        //去學校找出所屬校本預設班級信息
                         var query = $"SELECT c.code, c.id, c.name, c.periodId, c.gradeId FROM c JOIN cs IN c.students WHERE cs.id = '{id}'";
-                        await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Class-{school_code}") }))
+                        var school = client.GetContainer("TEAMModelOS", "School");
+                        await foreach (var item in school.GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Class-{school_code}") }))
                         {
-                            var jsoncm = await JsonDocument.ParseAsync(item.ContentStream);
-                            if (jsoncm.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                            using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                            if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
                             {
-                                foreach (var obj in jsoncm.RootElement.GetProperty("Documents").EnumerateArray())
+                                foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
                                 {
-                                    classinfo = obj.ToObject<object>();
-                                    classExistFlg = true;
+                                    classid = obj.GetProperty("id").GetString();
+                                    classinfo = obj.ToObject<object>();                                    
                                 }
                             }
                         }
-
-                        //換取AuthToken,提供給前端
-                        auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id.GetString(), name.GetString(), picture.GetString(), _option.JwtSecretKey, schoolID: school_code.GetString(), roles: new[] { "student" });
-
-                        //所屬班級的課程列表
-                        if (classExistFlg)
+                        //找出所屬班級的課程列表                                    
+                        var queryc = $"SELECT VALUE cc.course FROM c JOIN cc IN c.courses WHERE c.id = '{classid}'";
+                        await foreach (var item in school.GetItemQueryStreamIterator(queryText: queryc, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"CourseManagement-{school_code}") }))
                         {
-                            string classId = classinfo.GetProperty("id").ToString();
-                            var queryc = $"SELECT VALUE cc.course FROM c JOIN cc IN c.courses WHERE c.id = '{classId}'";
-                            await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: queryc, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"CourseManagement-{school_code}") }))
+                            using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                            if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
                             {
-                                using var jsoncm = await JsonDocument.ParseAsync(item.ContentStream);
-                                if (jsoncm.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                                foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
                                 {
-                                    foreach (var obj in jsoncm.RootElement.GetProperty("Documents").EnumerateArray())
-                                    {
-                                        courses.Add(obj.ToObject<object>());
-                                    }
+                                    courses.Add(obj.ToObject<object>());
                                 }
                             }
                         }
-                        else
-                        {
-                            classinfo = null;
-                        }
+                        // BLOB(學校,唯讀)
+                        var (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS(school_code.GetString().ToLower(), BlobContainerSasPermissions.Read);
+                        //換取AuthToken,提供給前端
+                        var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id.GetString(), name.GetString(), picture.GetString(), _option.JwtSecretKey, schoolID: school_code.GetString(), roles: new[] { "student" });
+                        return Ok(new { error = 0, auth_token, blob_uri, blob_sas, classinfo, courses });
                     }
                     else
                     {
-                        error = 1;
+                        return Ok(new { error = 1, message = "账号或密码错误" });
                     }
                 }
                 else
                 {
-                    error = 1;
-                }
-
-                if (error > 0)
-                {
-                    return Ok(new { error, message = "账号或密码错误" });
-                }
-                else
-                {
-                    return Ok(new { error, auth_token, blob_uri, blob_sas, classinfo, courses });
-                }
+                    return Ok(new { error = 2, message = "無此帳號存在" });
+                }                
             }
             catch (Exception ex)
             {
-                await _dingDing.SendBotMsg($"student/login,{_option.Location},hiteach/GetTeacherInfo()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
+                await _dingDing.SendBotMsg($"IES5,{_option.Location},student/login()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
                 return BadRequest();
             }
         }

+ 1 - 1
TEAMModelOS/Controllers/Teacher/InitController.cs

@@ -151,7 +151,7 @@ namespace TEAMModelOS.Controllers
             }
             catch (Exception ex)
             {
-                await _dingDing.SendBotMsg($"CoreAPI2,{_option.Location},hiteach/GetTeacherInfo()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
+                await _dingDing.SendBotMsg($"IES5,{_option.Location},Teacher/GetTeacherInfo()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
                 return BadRequest();
             }
         }

+ 0 - 5
TEAMModelOS/Models/Dto/VoteDto.cs

@@ -2,7 +2,6 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
-using TEAMModelOS.Models;
 using TEAMModelOS.SDK.Models;
 
 namespace TEAMModelOS.Models.Dto
@@ -10,10 +9,6 @@ namespace TEAMModelOS.Models.Dto
     public class VoteDto
     {
         public Vote vote { get; set; }
-
-        /// <summary>
-        /// 是否重置学生作业关联表数据
-        /// </summary>
         public bool reset { get; set; }
     }
 }

+ 0 - 37
TEAMModelOS/Models/Dto/VoteStudentDto.cs

@@ -1,37 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations;
-using System.Linq;
-using System.Threading.Tasks;
-
-namespace TEAMModelOS.Models.Dto
-{
-    public class VoteStudentDto
-    {
-        /// <summary>
-        /// 
-        /// </summary>
-        [Required(ErrorMessage = "{0} 必须填写")]
-        public string studentID { get; set; }
-
-        [Required(ErrorMessage = "{0} 必须填写")]
-        public string voteWorkId { get; set; }
-
-        /// <summary>
-        /// 选项
-        /// </summary>
-        [Required(ErrorMessage = "{0} 必须填写")]
-        public string option { get; set; }
-
-
-        //[ProtoContract]
-        //public class Option
-        //{
-        //    [ProtoMember(1)]
-        //    public string code { get; set; }
-
-        //    [ProtoMember(2)]
-        //    public string value { get; set; }
-        //}
-    }
-}

+ 6 - 2
TEAMModelOS/TEAMModelOS.csproj

@@ -6,7 +6,7 @@
   <ItemGroup>
     <PackageReference Include="Caching.CSRedis" Version="3.6.50" />
     <PackageReference Include="CSRedisCore" Version="3.6.5" />
-    <PackageReference Include="HTEXLib" Version="2.1.0" />
+    <PackageReference Include="HTEXLib" Version="2.1.5" />
     <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.6" />
       <PackageReference Include="VueCliMiddleware" Version="3.1.2" />  </ItemGroup>
   <PropertyGroup>
@@ -18,18 +18,23 @@
     <!-- Don't publish the SPA source files, but do show them in the project files list -->
     <Compile Remove="JsonFile\Subject\**" />
     <Compile Remove="logfile\**" />
+    <Compile Remove="Models\SchoolInfo\**" />
     <Content Remove="$(SpaRoot)**" />
     
     <Content Remove="JsonFile\Subject\**" />
     
     <Content Remove="logfile\**" />
+    
+    <Content Remove="Models\SchoolInfo\**" />
     <None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" />
   </ItemGroup>
   <ItemGroup>
     <EmbeddedResource Remove="JsonFile\Subject\**" />
     <EmbeddedResource Remove="logfile\**" />
+    <EmbeddedResource Remove="Models\SchoolInfo\**" />
     <None Remove="JsonFile\Subject\**" />
     <None Remove="logfile\**" />
+    <None Remove="Models\SchoolInfo\**" />
   </ItemGroup>
   <ItemGroup>
     <None Remove="ClientApp\src\static\BaseDataDefault.json" />
@@ -44,7 +49,6 @@
 
   <ItemGroup>
     <Folder Include="JwtRsaFile\" />
-    <Folder Include="Models\SchoolInfo\" />
     <Folder Include="Services\Evaluation\" />
     <Folder Include="wwwroot\" />
   </ItemGroup>