فهرست منبع

Merge branch 'develop' into PL/develop-BI

Li 2 سال پیش
والد
کامیت
cb5e44b1bf
44فایلهای تغییر یافته به همراه5383 افزوده شده و 892 حذف شده
  1. 4 4
      TEAMModelOS.FunctionV4/HttpTrigger/IESHttpTrigger.cs
  2. 10 0
      TEAMModelOS.SDK/Models/Cosmos/Normal/ArtSetting.cs
  3. 11 1
      TEAMModelOS.SDK/Models/Cosmos/School/Inner/Period.cs
  4. 47 16
      TEAMModelOS/ClientApp/public/lang/en-US.js
  5. 35 5
      TEAMModelOS/ClientApp/public/lang/zh-CN.js
  6. 35 5
      TEAMModelOS/ClientApp/public/lang/zh-TW.js
  7. 0 4
      TEAMModelOS/ClientApp/src/api/courseMgmt.js
  8. 506 0
      TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/RecordView.less
  9. 862 0
      TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/RecordView.vue
  10. 2 2
      TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/ShowQues.vue
  11. 61 49
      TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/newDataCount.vue
  12. 281 0
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/Homework.less
  13. 174 214
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/Homework.vue
  14. 51 0
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/HomeworkiView.less
  15. 16 13
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperViewBox/PaperView.less
  16. 9 8
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperViewBox/PaperView.vue
  17. 1 1
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperViewBox/PaperView-style.less
  18. 61 95
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/QuesNaire.vue
  19. 141 0
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/Quesnaire.less
  20. 35 0
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/QuesnaireiView.less
  21. 89 139
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/Vote.vue
  22. 179 0
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/vote.less
  23. 62 0
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/voteiView.less
  24. 165 133
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventList.less
  25. 124 40
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventList.vue
  26. 1 0
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventView.vue
  27. 4 11
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventiView.less
  28. 130 3
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeView.less
  29. 788 0
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/newHomeView.vue
  30. 26 0
      TEAMModelOS/ClientApp/src/components/student-web/StudyView/StudyList.less
  31. 344 0
      TEAMModelOS/ClientApp/src/components/student-web/StudyView/StudyViews.vue
  32. 4 4
      TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/WrongQues.vue
  33. 115 94
      TEAMModelOS/ClientApp/src/components/student-web/achievement/MyAchievement.vue
  34. 77 0
      TEAMModelOS/ClientApp/src/components/student-web/achievement/SchoolReport.less
  35. 324 0
      TEAMModelOS/ClientApp/src/components/student-web/achievement/SchoolReport.vue
  36. 104 0
      TEAMModelOS/ClientApp/src/components/student-web/common-style.less
  37. 9 2
      TEAMModelOS/ClientApp/src/router/routes.js
  38. 2 0
      TEAMModelOS/ClientApp/src/store/index.js
  39. 15 1
      TEAMModelOS/ClientApp/src/store/module/studentWeb.js
  40. 1 1
      TEAMModelOS/ClientApp/src/view/student-account/class/ClassMgt.vue
  41. 2 2
      TEAMModelOS/ClientApp/src/view/student-account/import/StuImport.vue
  42. 6 0
      TEAMModelOS/ClientApp/src/view/student-web/App.less
  43. 431 40
      TEAMModelOS/ClientApp/src/view/student-web/AppNew.vue
  44. 39 5
      TEAMModelOS/ClientApp/src/view/student-web/AppiView.less

+ 4 - 4
TEAMModelOS.FunctionV4/HttpTrigger/IESHttpTrigger.cs

@@ -92,13 +92,13 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
                            .GetItemQueryIterator<School>(queryText: schoolSQL, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Base") }))
             {
                 schools.Add(item);
-            }
+            }           
             ArtSetting artSetting= await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).ReadItemAsync<ArtSetting>($"{_areaId}", new PartitionKey());
             foreach (var school in schools) {
-                var periods = school.period.Where(p => !string.IsNullOrWhiteSpace(p.type));
+                var periods = school.period.Where(p => p.type.IsNotEmpty());
                 foreach (var period in periods)
                 {
-                    var dimension = artSetting.dimensions.FindAll(x => x.type.Contains(period.type));
+                    var dimension = artSetting.dimensions.FindAll(x => x.type.Intersect(period.type).Any());
                     var bindIds = period.subjects.Where(s => !string.IsNullOrWhiteSpace(s.bindId)).Select(x => x.bindId);
                     //该学段未同步学科的。
                     var unBindIds = dimension.Where(z => !string.IsNullOrWhiteSpace(z.subjectBind)).Select(x => x.subjectBind).ToHashSet().Except(bindIds);
@@ -146,7 +146,7 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
                             //同步知识块。
                             if (old != null)
                             {
-                             
+                                
                             }
                             else { 
                                 

+ 10 - 0
TEAMModelOS.SDK/Models/Cosmos/Normal/ArtSetting.cs

@@ -75,6 +75,16 @@ namespace TEAMModelOS.SDK.Models
         ///     成人高等教育:成人高等
         /// 学前 period_pre,小学period_primary,初中period_junior,高中period_senior,中职(中专,技校,职高)period_secondary, 高职(专科)period_college,大学本科period_university,硕士研究生学段period_master,博士研究生学段period_doctor,特殊教育period_special ,成人中专period_adult-secondary,成人高教period_adult-higher,其它period_other
         /// "学前","小学","初中","高中","中职(中专,技校,职高)"," 高职(专科)","大学本科","硕士研究生学段","博士研究生学段","特殊教育","成人中专","成人高教","其它"
+        ///   {"pre" ,"学前"},
+        //{"primary","小学"},
+        //{"junior","初中"},
+        //{ "senior","高中" },
+        //{ "secondary","中职(中专,技校,职高)" },
+        //{ "college","高职(专科)"},
+        //{ "university","大学本科"},
+        //{ "special","特殊教育"},
+        //{ "edu-bureau","教育局"},
+        //{ "elecedu-dept","电教部门"},
         /// </summary>
         public List<string> type { get; set; } = new List<string>();
     }

+ 11 - 1
TEAMModelOS.SDK/Models/Cosmos/School/Inner/Period.cs

@@ -35,7 +35,17 @@ namespace TEAMModelOS.SDK.Models
         /// </summary>
         public List<TimeTable> timetable { get; set; } = new List<TimeTable>();
         //"学前","小学","初中","高中","中职(中专,技校,职高)","高职(专科)","大学本科","特殊教育","教育局","电教部门"
-        public string type { get; set; }
+        //{"pre" ,"学前"},
+        //{"primary","小学"},
+        //{"junior","初中"},
+        //{ "senior","高中" },
+        //{ "secondary","中职(中专,技校,职高)" },
+        //{ "college","高职(专科)"},
+        //{ "university","大学本科"},
+        //{ "special","特殊教育"},
+        //{ "edu-bureau","教育局"},
+        //{ "elecedu-dept","电教部门"},
+        public List<string> type { get; set; }= new List<string>();
     }
 
     /// <summary>

+ 47 - 16
TEAMModelOS/ClientApp/public/lang/en-US.js

@@ -2857,7 +2857,7 @@ const LANG_EN_US = {
             orderIndex: 'Serial No.',
             quNo: 'Question No.',
             teaCount: 'Teacher No.',
-            markCount: '閱卷量',
+            markCount1: '閱卷量',
             delBlockTitle: 'Delete Assignment',
             delBlockCont: 'Are you sure to delete the current question assignment settings?',
             selectQuTips: 'Please select a question to be assigned',
@@ -4160,17 +4160,24 @@ const LANG_EN_US = {
             survey: 'Survey',
             homework: 'Homework',
             title: {
-                classRecord: "Lesson records posted by teachers",
-                activity: "Activities started by teachers",
-                notice1: "Class Announcement",
+                classRecord: "Latest Lesson Records",
+                activity: "Latest Tasks",
+                notice1: "Announces",
                 notice2: "Course Announcement",
                 exam: "Assessment Grade Analysis",
                 homework: "Homework Rating",
                 classScore: "Lesson Point",
+                joinClass: "My Courses",
+                title1: "You have not joined the course",
+                title2: "Input the invitation code and join the course",
             },
             toLook: "See now",
             tip1: "No. ",
             tip2: "",
+            timeType: {
+                title1: "Recent",
+                title2: "Due Today",
+            },
         },
         public: {
             noData: 'No data yet',
@@ -4244,18 +4251,41 @@ const LANG_EN_US = {
             value: "connector"
         },
         ],
-        state: [{
-            type: 'All',
-            status: 'All Activity Status'
-        },
-        {
-            type: 'going',
-            status: 'In progress'
-        },
-        {
-            type: 'finish',
-            status: 'Completed'
-        }
+        state1: [
+            {
+                type: 'all',
+                status: 'All Activity Status'
+            },
+            {
+                type: 'going',
+                status: 'In progress'
+            },
+            {
+                type: 'finish',
+                status: 'Completed'
+            },
+            {
+                type: 'noScore',
+                status: 'Not Graded'
+            },
+            {
+                type: 'noAns',
+                status: 'Absent'
+            }
+        ],
+        state2: [
+            {
+                type: 'All',
+                status: 'All Activity Status'
+            },
+            {
+                type: 'going',
+                status: 'In progress'
+            },
+            {
+                type: 'finish',
+                status: 'Has ended'
+            }
         ],
         event: {
             allStatus: 'All Activity Status',
@@ -4532,6 +4562,7 @@ const LANG_EN_US = {
                 month: "Monthly",
                 year: "Yearly",
             },
+            choiceTeacher: "Filter Teacher",
         },
         homework: {
             homeworkShow: 'Answering Record',

+ 35 - 5
TEAMModelOS/ClientApp/public/lang/zh-CN.js

@@ -2857,7 +2857,7 @@ const LANG_ZH_CN = {
             orderIndex: '序号',
             quNo: '题号',
             teaCount: '教师人数',
-            markCount: '阅卷量',
+            markCount1: '阅卷量',
             delBlockTitle: '删除题块',
             delBlockCont: '确认删除当前题块设置吗?',
             selectQuTips: '请选择题目进行划块',
@@ -4162,17 +4162,24 @@ const LANG_ZH_CN = {
             survey: '问卷',
             homework: '作业',
             title: {
-                classRecord: "老师发布的课堂记录",
-                activity: "老师发布的活动",
-                notice1: "班级公告",
+                classRecord: "最新的课堂记录",
+                activity: "最新的活动任务",
+                notice1: "联络簿/公告",
                 notice2: "课程公告",
                 exam: "评测成绩分析",
                 homework: "作业评分",
                 classScore: "课例记分",
+                joinClass: "我参与学习的课程",
+                title1: "您还没有加入课程",
+                title2: "快去输入邀请码,加入课程进行学习吧",
             },
             toLook: "现在去看",
             tip1: "第",
             tip2: "次",
+            timeType: {
+                title1: "近期",
+                title2: "今日到期",
+            },
         },
         public: {
             noData: '暂无数据',
@@ -4247,7 +4254,7 @@ const LANG_ZH_CN = {
                 value: "connector"
             }
         ],
-        state: [
+        state1: [
             {
                 type: 'all',
                 status: '所有活动状态'
@@ -4259,8 +4266,30 @@ const LANG_ZH_CN = {
             {
                 type: 'finish',
                 status: '已完成'
+            },
+            {
+                type: 'noScore',
+                status: '未评分'
+            },
+            {
+                type: 'noAns',
+                status: '缺考'
             }
         ],
+        state2: [
+            {
+                type: 'all',
+                status: '所有活动状态'
+            },
+            {
+                type: 'going',
+                status: '进行中'
+            },
+            {
+                type: 'finish',
+                status: '已结束'
+            },
+        ],
         event: {
             allStatus: '所有活动状态',
             unFinished: '未完成',
@@ -4536,6 +4565,7 @@ const LANG_ZH_CN = {
                 month: "每月",
                 year: "每年",
             },
+            choiceTeacher: "筛选老师",
         },
         homework: {
             homeworkShow: '作答记录',

+ 35 - 5
TEAMModelOS/ClientApp/public/lang/zh-TW.js

@@ -2858,7 +2858,7 @@ const LANG_ZH_TW = {
             orderIndex: '序號',
             quNo: '題號',
             teaCount: '教師人數',
-            markCount: '閱卷量',
+            markCount1: '閱卷量',
             delBlockTitle: '刪除題塊',
             delBlockCont: '確認刪除當前題塊設定嗎?',
             selectQuTips: '請選擇題目進行劃塊',
@@ -4163,17 +4163,24 @@ const LANG_ZH_TW = {
             survey: '問卷',
             homework: '作業',
             title: {
-                classRecord: "教師發布的課堂記錄",
-                activity: "教師發布的活動",
-                notice1: "班級公告",
+                classRecord: "最新的課堂記錄",
+                activity: "最新的活動任務",
+                notice1: "聯絡簿/公告",
                 notice2: "課程公告",
                 exam: "評量成績分析",
                 homework: "作業評分",
                 classScore: "課例記分",
+                joinClass: "我參與學習的課程",
+                title1: "您還沒有加入課程",
+                title2: "快去輸入邀請碼,加入課程進行學習吧",
             },
             toLook: "現在去看",
             tip1: "第",
             tip2: "次",
+            timeType: {
+                title1: "近期",
+                title2: "今日到期",
+            },
         },
         public: {
             noData: '暫無資料',
@@ -4248,7 +4255,7 @@ const LANG_ZH_TW = {
                 value: "connector"
             }
         ],
-        state: [
+        state1: [
             {
                 type: 'all',
                 status: '所有活動狀態'
@@ -4260,6 +4267,28 @@ const LANG_ZH_TW = {
             {
                 type: 'finish',
                 status: '已完成'
+            },
+            {
+                type: 'noScore',
+                status: '未評分'
+            },
+            {
+                type: 'noAns',
+                status: '缺考'
+            }
+        ],
+        state2: [
+            {
+                type: 'all',
+                status: '所有活動狀態'
+            },
+            {
+                type: 'going',
+                status: '進行中'
+            },
+            {
+                type: 'finish',
+                status: '已結束'
             }
         ],
         event: {
@@ -4537,6 +4566,7 @@ const LANG_ZH_TW = {
                 month: "每月",
                 year: "每年",
             },
+            choiceTeacher: "篩選教師",
         },
         homework: {
             homeworkShow: '作答記錄',

+ 0 - 4
TEAMModelOS/ClientApp/src/api/courseMgmt.js

@@ -15,10 +15,6 @@ export default {
     deleteCourse: function (data) {
         return post('/school/course/delete', data)
     },
-    //获取教师列表
-    getSchoolTeacher: function (data) {
-        return post('/school/teacher/get-teacher-all', data)
-    },
     //更新保存标准课程公告
     upsertNotice: function (data) {
         return post('/school/course/upsert-notice', data)

+ 506 - 0
TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/RecordView.less

@@ -0,0 +1,506 @@
+@import '~@/assets/student-web/component_styles/color.less';
+
+.record-view {
+    /* height: 100%;
+    display: flex; */
+
+    .list-block-box {
+        /* // border-right: 1px solid @border;
+        height: 100%;
+        overflow: auto;
+        margin-top: 0px;
+        padding-bottom: 10px;
+        // width: 25%;
+        z-index: 2;
+        background-color: #fff;
+        box-shadow: 4px 1px 10px rgba(0, 0, 0, 0.1);
+        // border-right: 1px solid rgba(0, 0, 0, 0.1);
+        width: 25%; */
+
+        .list-item {
+            list-style-type: none;
+            width: 100%;
+            border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+            padding: 15px 10px 15px 15px;
+            position: relative;
+
+            &:hover {
+                background: linear-gradient(-0.75turn, #fafafa, #d4ede1);
+                color: #03966a;
+                cursor: pointer;
+            }
+
+            .list-item-info {
+                padding-right: 20px;
+                position: relative;
+                display: flex;
+
+                .list-item-title {
+                    font-weight: bolder;
+                    font-size: 14px;
+                    line-height: 22px;
+                }
+
+                .list-item-time {
+                    span {
+                        display: block;
+                    }
+                }
+            }
+
+            .record-poster-wrap {
+                width: 120px;
+                height: 65px;
+                background-size: contain;
+                background-repeat: no-repeat;
+                background-position: center;
+                margin-right: 20px;
+            }
+
+            .upload {
+                position: absolute;
+                top: 40%;
+                right: 20px;
+            }
+        }
+
+        .list-item-selected {
+            background: linear-gradient(-0.75turn, #fafafa, #d4ede1);
+            color: #03966a;
+            cursor: pointer;
+            // width: 100%;
+        }
+    }
+
+    .record-view-right {
+        /* width: 75%;
+        height: 100%;
+        // margin-top: 44px;
+        padding: 30px 20px 30px 30px; */
+
+        .record-head {
+            display: flex;
+            justify-content: space-between;
+    
+            &>div>p {
+                margin-bottom: 5px;
+            }
+    
+            .attend-type {
+                transform: rotate(338deg);
+                font-size: 17px;
+                font-weight: bold;
+            }
+        }
+    
+        img {
+            border-radius: 4px;
+            margin-right: 20px;
+            border: 1px solid rgba(173, 173, 173, 0.233);
+            width: 100%;
+        }
+    
+        .video-player-box {
+            // width: 50%;
+            justify-content: center;
+            height: 450px;
+            display: flex;
+            // margin-left: 5px;
+            position: relative;
+            // background-color: #fff;
+
+            
+            .no-video-tips {
+                position: absolute;
+                top: 0px;
+                left: 0px;
+                color: #ff9900;
+                width: 100%;
+            }
+        }
+    
+        .message-area {
+            position: relative;
+            height: 75vh;
+            padding: 10px;
+            margin-bottom: 20px;
+    
+            .filter-type {
+                position: absolute;
+                right: 0;
+                top: 10px;
+                padding-right: 10px;
+                padding-left: 10px;
+                text-align: center;
+                z-index: 9;
+                display: flex;
+                flex-direction: column;
+                background-color: #F1F1F1;
+    
+                span {
+                    border: none;
+                    padding: 0px;
+                    font-size: 32px;
+    
+                    &:hover {
+                        cursor: pointer;
+                        color: #24b880;
+                    }
+    
+                    .select-filter {
+                        color: #24b880;
+                    }
+                }
+            }
+    
+            .message-box {
+                display: flex;
+                border-bottom: 1px #ccc solid;
+    
+                .message-page {
+                    // width: 10%;
+                    padding: 10px 15px;
+                    padding-bottom: 0;
+                    // border-right: 1px #ccc dashed;
+    
+                    img {
+                        margin-top: 5px;
+                        margin-right: 0;
+                        width: 130px;
+                        cursor: pointer;
+                    }
+    
+                    .messagetoPPT-tag {
+                        background-color: rgba(0, 0, 0, 0.1);
+                        white-space: initial;
+                        display: block;
+                        font-size: 14px;
+                        height: auto;
+                        padding: 3px 10px;
+                        border-radius: 4px;
+    
+                        &:hover {
+                            cursor: pointer;
+                            color: #ffffff;
+                            background-color: #24b880;
+                        }
+                    }
+                }
+    
+                .message-record {
+                    padding: 10px 15px;
+                    padding-bottom: 0;
+                    width: calc(100% - 160px);
+                    // min-width: 780px;
+    
+                    .message-item {
+                        white-space: nowrap;
+                        display: block;
+                        position: relative;
+                        padding-top: 20px;
+                        margin-bottom: 50px;
+    
+                        .message-avatar {
+                            border-radius: 50%;
+                            float: left;
+                            width: 32px !important;
+                            height: 32px !important;
+                            margin: 0px 15px;
+                            margin-top: -10px;
+                        }
+    
+                        .user-name {
+                            white-space: nowrap;
+                            font-weight: bolder;
+                            position: absolute;
+                            top: 0;
+                            left: 55px;
+                            // position: absolute;
+                            // top: -12px;
+                            // margin-left: -8px;
+                        }
+    
+                        .message-content {
+                            background: #d4ede1;
+                            padding: 10px;
+                            display: inline-block;
+                            border-radius: 4px;
+                            position: relative;
+                            // width: 85%;
+    
+                            &::before {
+                                content: "";
+                                position: absolute;
+                                top: 3px;
+                                // margin-left: -16px;
+                                left: -7px;
+                                width: 0;
+                                height: 0;
+                                border-style: solid;
+                                border-width: 5px 7.7px 5px 0;
+                                border-color: transparent #d4ede1 transparent transparent;
+                            }
+    
+                            .message-text {
+                                img {
+                                    max-width: 80%;
+                                }
+    
+                                .pick-item {
+                                    width: 100px;
+                                    text-align: center;
+                                    background: rgba(0, 0, 0, 0.3);
+                                    height: 100px;
+                                    border: 2px solid #ff9900;
+                                    border-radius: 8px;
+                                    display: flex;
+                                    flex-direction: column;
+                                    justify-content: center;
+    
+                                    .student-no {
+                                        font-size: 40px;
+                                        color: black;
+                                        font-weight: 600;
+                                    }
+    
+                                    .student-name {
+                                        color: #007cff;
+                                        font-weight: 800;
+                                        font-size: 16px;
+                                    }
+                                }
+                            }
+    
+                        }
+    
+                        .message-time {
+                            white-space: nowrap;
+                            color: gray;
+                            font-size: 10px;
+                            font-weight: 400;
+                            // position: absolute;
+                            // bottom: -20px;
+                            // margin-left: -8px;
+                            position: absolute;
+                            // bottom: 0;
+                            left: 55px;
+                        }
+                    }
+    
+                    .teacher-item {
+                        display: block;
+                        // padding-right: 5%;
+                        text-align: right !important;
+                        position: relative;
+                        margin-bottom: 50px;
+    
+                        .message-avatar {
+                            border-radius: 50%;
+                            float: left;
+                            width: 32px !important;
+                            height: 32px !important;
+                            margin: 0px 15px;
+                            margin-top: -10px;
+                        }
+    
+                        .user-name {
+                            white-space: nowrap;
+                            font-weight: bolder;
+                            position: absolute;
+                            top: 0;
+                            left: 55px;
+                            // position: absolute;
+                            // top: -12px;
+                            // margin-left: -8px;
+                        }
+    
+                        .message-content {
+                            background: #ffecc2;
+                            padding: 10px;
+                            display: inline-block;
+                            border-radius: 4px;
+                            position: relative;
+                            // width: 85%;
+    
+                            &::before {
+                                content: "";
+                                position: absolute;
+                                top: 3px;
+                                // margin-left: -16px;
+                                right: -9px;
+                                width: 0;
+                                height: 0;
+                                border-style: solid;
+                                border-width: 5px 0 5px 8.7px;
+                                border-color: transparent transparent transparent #ffecc2;
+                            }
+    
+                            .message-text {
+                                img {
+                                    max-width: 80%;
+                                }
+    
+                                .pick-item {
+                                    width: 100px;
+                                    text-align: center;
+                                    background: rgba(0, 0, 0, 0.3);
+                                    height: 100px;
+                                    border: 2px solid #ff9900;
+                                    border-radius: 8px;
+                                    display: flex;
+                                    flex-direction: column;
+                                    justify-content: center;
+    
+                                    .student-no {
+                                        font-size: 40px;
+                                        color: black;
+                                        font-weight: 600;
+                                    }
+    
+                                    .student-name {
+                                        color: #007cff;
+                                        font-weight: 800;
+                                        font-size: 16px;
+                                    }
+                                }
+                            }
+    
+                        }
+    
+                        .message-time {
+                            white-space: nowrap;
+                            color: gray;
+                            font-size: 10px;
+                            font-weight: 400;
+                            // position: absolute;
+                            // bottom: -20px;
+                            // margin-left: -8px;
+                            position: absolute;
+                            // bottom: 0;
+                            right: 55px;
+                        }
+                    }
+    
+                    .teacher-client-icon {
+                        font-size: 30px;
+                        padding: 5px;
+                        color: #ffffff;
+                        border-radius: 50%;
+                        background: #19be6b;
+                        margin-right: 15px;
+                        float: left;
+                    }
+    
+                    .student-client-icon {
+                        font-size: 30px;
+                        padding: 5px;
+                        color: #ffffff;
+                        border-radius: 50%;
+                        background: #efbb49;
+                        float: right;
+                        margin-left: 15px;
+                    }
+    
+                    .event-item {
+                        border: 1px dashed transparent;
+                        margin-bottom: 15px;
+                        padding: 5px 5px;
+                        overflow-x: scroll;
+                        
+                        &:hover {
+                            border: 1px dashed #e0e0e0;
+                        }
+                    }
+    
+                    .student-event {
+                        display: flex;
+                        justify-content: end;
+                    }
+                }
+            }
+        }
+    
+        .title-rect-name>span {
+            background-color: #24B880;
+            font-size: 12px;
+            padding: 3px;
+            border: 1px solid #ccc;
+            border-radius: 4px;
+            color: #fff;
+            cursor: pointer;
+        }
+
+        .courseware-wrap {
+            // width: 50%;
+            position: relative;
+            height: 450px;
+            background-color: #808080;
+            margin-top: 10px;
+            // margin-right: 5px;
+        
+            .page-wrap {
+                opacity: 1;
+            }
+        
+            .cur-page-tag {
+                opacity: 0;
+            }
+        
+            .course-cur-img {
+                height: 100%;
+            }
+        }
+
+        .page-wrap {
+            left: 0px;
+            bottom: 0px;
+            position: absolute;
+            padding: 6px;
+            color: white;
+            width: 100%;
+            height: 36px;
+            background: rgba(43, 51, 63, 0.7);
+            text-align: center;
+            opacity: 0;
+            transition: opacity 1.2s;
+            border-right: 2px solid black;
+        }
+
+        .record-content {
+            height: calc(100% - 64px);
+            display: flex;
+            justify-content: space-between;
+            
+            .record-left {
+                width: 39%;
+                height: 100%;
+    
+                & > div{
+                    margin-top: 10px;
+                }
+            }
+    
+            .record-right {
+                width: 60%;
+                height: 100%;
+                
+                .dec {
+                    height: calc(100% - 62px);
+                    padding: 0px;
+                    // height: 800px;
+                    overflow: hidden;
+                    position: relative;
+                    margin-top: 10px;
+            
+                    .no-interaction {
+                        height: 100%;
+                        text-align: center;
+                        font-size: 20px;
+                        margin-top: 80px;
+                        font-weight: bold;
+                    }
+                }
+            }
+        }
+    }
+}

+ 862 - 0
TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/RecordView.vue

@@ -0,0 +1,862 @@
+<template>
+    <div class="layout-content-wrap record-view">
+        <Loading v-show="isLoad" bgColor="rgba(0, 0, 0, 0.3)"></Loading>
+        <div class="layout-left-wrap list-block-box" v-show="getSidebarisOpen">
+            <template v-if="recordList.length">
+                <Scroll :on-reach-bottom="handleReachTop" class="scroll-list">
+                    <div v-for="(item, index) in recordList" :key="index" @click="toClassRecord(item, index)"
+                        :class="['list-item', {'list-item-selected': nowIndex === index}]">
+                        <ul>
+                            <li class="list-item-info">
+                                <RcdPoster class="record-poster-wrap" :poster="item.CoverImage"></RcdPoster>
+                                <div>
+                                    <p class="list-item-title">
+                                        <span>{{ item.name }}</span>
+                                        <!-- <span style="margin-left: 20px">老师:{{ item.teacher }}</span> -->
+                                    </p>
+                                    <p class="list-item-time">
+                                        <span>{{ item.startTime }}</span>
+                                        <span>{{ $t('studentWeb.baseInfo.duration') }}:{{ item.time }}</span>
+                                    </p>
+                                </div>
+                            </li>
+                            <span class="upload">
+                                <span v-show="item.myNote.length" @click.capture.stop="uploadNote(item, true)">
+                                    <Icon custom="iconfont icon-myNote" size="20" :title="$t('studentWeb.courseContent.mynotes')" />
+                                </span>
+                                <span style="margin-left: 15px;" @click.capture.stop="uploadNote(item)">
+                                    <Icon custom="iconfont icon-activityT" size="20" :title="$t('studentWeb.courseContent.notes')" />
+                                </span>
+                            </span>
+                        </ul>
+                    </div>
+                </Scroll>
+            </template>
+            <div v-else style="margin-top: 15px; font-size: 15px; text-align: center;">{{ $t('studentWeb.courseContent.noClassRecord') }}</div>
+        </div>
+        <div class="layout-right-wrap record-view-right" :class="{'no-bar-content': getSidebarisOpen}" v-if="recordInfo">
+            <!-- <div style="margin-top: 44px; padding: 10px 15px;"> -->
+                <h2 class="event-title">{{ recordInfo.name }}</h2>
+                <div style="text-align: right; margin-bottom: 5px;">
+                    <!-- <Button type="primary" @click="showWorks = true" :disabled="!myWorks.length">
+                        <Icon custom="iconfont icon-zuopin" size="16" />
+                        {{ $t('studentWeb.courseContent.myWorks') }}
+                    </Button> -->
+                    <!-- <Button type="primary" @click="showNote = true" v-if="recordInfo.myNote.length">
+                        <Icon custom="iconfont icon-myNote" size="17" />
+                        {{ $t('studentWeb.courseContent.mynotes') }}
+                    </Button> -->
+                    <Button type="primary" @click="viewENote">
+                        <Icon custom="iconfont icon-activityT" />
+                        {{ $t('studentWeb.courseContent.notes') }}
+                    </Button>
+                    <Button type="primary" @click="isShowVd = !isShowVd" v-show="hasVideo">
+                        <Icon :type="isShowVd ? 'md-podium' : 'logo-youtube'" />
+                        {{ isShowVd ? $t('cusMgt.rcd.dataCount') : $t('cusMgt.rcd.videoData') }}
+                    </Button>
+                </div>
+                <div class="record-content">
+                    <div class="record-left">
+                        <vuescroll>
+                            <div style="padding-right: 10px; height: 100%;">
+                                <div class="record-head">
+                                    <div>
+                                        <p style="margin-left: 20px;">
+                                            <Icon type="ios-contact-outline" style="font-weight: bold;" class="base-info-icon" />{{ $t('studentWeb.baseInfo.teacher') }}
+                                            <span class="base-info-text">{{ recordInfo.tmdname }}</span>
+                                        </p>
+                                        <template>
+                                            <p style="margin-left: 20px;">
+                                                <svg-icon class="base-info-icon" icon-class="course" />{{ $t('studentWeb.baseInfo.subjectName') }}
+                                                <span class="base-info-text">{{ courseNow.name }}</span>
+                                            </p>
+                                            <p style="margin-left: 20px;">
+                                                <Icon custom="iconfont icon-mingdan" class="base-info-icon" />{{ $t('studentWeb.baseInfo.stuList') }}
+                                                <span class="base-info-text">{{ courseNow.listName }}</span>
+                                            </p>
+                                        </template>
+                                        <p style="margin-left: 20px;">
+                                            <Icon type="md-timer" class="base-info-icon" />{{ $t('studentWeb.baseInfo.duration') }}:
+                                            <span class="base-info-text">{{ recordInfo.time }}</span>
+                                        </p>
+                                        <p style="margin-left: 20px;">
+                                            <svg-icon icon-class="time" class="base-info-icon" />{{$t('studentWeb.baseInfo.classTime')}}:
+                                            <span class="base-info-text">{{ recordInfo.startTime }}</span>
+                                        </p>
+                                    </div>
+                                    <div>
+                                        <i-circle :percent="100" :size="100" :stroke-width="10" :stroke-color="attentColor[attendType]">
+                                            <p class="attend-type">{{ $t(`studentWeb.hiteachNote.dataCount.attendTypeList[${attendType}]`) }}</p>
+                                        </i-circle>
+                                    </div>
+                                </div>
+                                <div v-if="hasVideo" v-show="isShowVd" class="video-player-box">
+                                    <video style="width: 100%;" :id="'recordVideo' + recordInfo.id" class="video-js vjs-default-skin" type="video/mp4"></video>
+                                </div>
+                                <div v-show="!isShowVd" class="video-player-box" style="padding:25px 0px">
+                                    <Alert v-show="!hasVideo" class="no-video-tips" type="warning" show-icon>
+                                        {{$t('cusMgt.rcd.noVideo')}}
+                                    </Alert>
+                                    <DataCount :nowStuInfo="nowStuInfo" :rcdInfo="baseData" v-if="baseData"></DataCount>
+                                </div>
+                                <div class="courseware-wrap">
+                                    <!-- <DrawHTEX :mapJson="mapJson"></DrawHTEX> -->
+                                    <img :src="curImg" alt="" class="course-cur-img">
+                                    <div class="page-wrap">
+                                        <Page :total="pageList.length" :current="curPage" :page-size="1" size="small" @on-change="getCurHTEX" />
+                                        <!-- <Icon v-if="pageList.length" type="md-qr-scanner" class="full-screen-icon" @click="viewHtex" /> -->
+                                    </div>
+                                    <!-- <span class="cur-page-tag">{{ curPage }}</span> -->
+                                </div>
+                            </div>
+                        </vuescroll>
+                    </div>
+                    <div class="record-right">
+                        <div>
+                            <h2 class="title-rect-name">
+                                {{ $t("studentWeb.hiteachNote.classInteractionRecord") }}
+                            </h2>
+                            <div style="width: 100%; display: flex; justify-content: space-between;">
+                                <div>
+                                    <!-- <Button type="primary">时间</Button>
+                                    <Button type="primary">页次</Button> -->
+                                </div>
+                                <div>
+                                    <Button type="warning" @click="filterFn('all')">{{ $t("cusMgt.rcd.filter1") }}</Button>
+                                    <Button type="warning" :disabled="!filtertype.push" @click="filterFn('push')">{{ $t("cusMgt.rcd.filter2") }}({{ filtertype.push }})</Button>
+                                    <Button type="warning" :disabled="!filtertype.task" @click="filterFn('task')">{{ $t("cusMgt.rcd.filter3") }}({{ filtertype.task }})</Button>
+                                    <Button type="warning" :disabled="!filtertype.irs" @click="filterFn('irs')">{{ $t("cusMgt.rcd.filter4") }}({{ filtertype.irs }})</Button>
+                                    <Button type="warning" :disabled="!filtertype.exam" @click="filterFn('exam')">{{ $t("cusMgt.rcd.filter5") }}({{ filtertype.exam }})</Button>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="dec">
+                            <div class="message-area" v-if="haveInteraction">
+                                <vuescroll ref="datawrap">
+                                    <div style="margin-bottom: 50px;">
+                                        <div v-for="(items, index) in showPageList" :key="index" :id="'page' + (items.page)">
+                                            <div v-if="items.pageData.length" class="message-box">
+                                                <div class="message-page">
+                                                    <div @click="toVideo(index + 1, $event)">
+                                                        <img :src="items.img" @click="openViewer(items.img)">
+                                                    </div>
+                                                </div>
+                                                <div class="message-record">
+                                                    <template v-if="items.pageData.length">
+                                                        <div v-for="event in items.pageData" :key="event.Time">
+                                                            <!-- 即问即答 -->
+                                                            <div v-if="currentfilterType === '' || currentfilterType === 'ShowAnsLoad'">
+                                                                <ShowQues class="event-item student-event" v-if="event.Event === 'PopQuesLoad' || event.Event === 'ReAtmpAnsStrt'" :nowStuInfo="nowStuInfo" :evtType="event.Event" :irsData="event.data"></ShowQues>
+                                                                <PopQues class="event-item" v-if="event.Event === 'PopQuesLoad' || event.Event === 'ReAtmpAnsStrt'" :evtType="event.Event" :irsData="event.data"></PopQues>
+                                                            </div>
+                                                            <!-- 抢权 -->
+                                                            <Buzr class="event-item student-event" v-if="event.Event === 'BuzrAns' && baseData" :buzrData="event.data" :students="baseData.student"></Buzr>
+                                                            <!-- 推送 -->
+                                                            <Push class="event-item" v-if="event.Event === 'FastPgPush' && (currentfilterType === '' || currentfilterType === 'doc')" :pushData="event.data"></Push>
+                                                            <!-- 作品收集 -->
+                                                            <StuReceive class="student-event event-item" v-if="event.Event === 'WrkSpaceLoad' && baseData" :nowStuInfo="nowStuInfo" :rcvData="event.data" :recordInfo="recordInfo" :students="baseData.student"></StuReceive>
+                                                            <!-- 老师收集的所有作品目前不展示,只展示老师回贴的学生作品 -->
+                                                            <!-- <Receive :recordInfo="recordInfo" class="student-event event-item" v-if="event.Event === 'WrkCmp' && baseData" :rcvData="event.data" :students="baseData.student"></Receive> -->
+                                                            <ReceiveBack class="event-item" v-if="event.Event === 'WrkCmp' && event.data && baseData" :recordInfo="recordInfo" :rcvData="event.data" :students="baseData.student"></ReceiveBack>
+                                                            <!-- 随机挑人 -->
+                                                            <Pick class="event-item student-event" v-if="event.Event === 'PickupResult' && baseData" :pickData="event.data" :students="baseData.student"></Pick>
+                                                            <!-- 课中评测 -->
+                                                            <Exam class="student-event event-item" :examInfo="event.data" :recordInfo="recordInfo" v-if="event.Event === 'SPQStrt'"></Exam>
+                                                        </div>
+                                                    </template>
+                                                </div>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </vuescroll>
+                            </div>
+                            <div v-else class="no-interaction">
+                                {{ $t("studentWeb.hiteachNote.noContent") }}
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            <!-- </div> -->
+        </div>
+        <Modal v-model="showNote" :title="$t('studentWeb.courseContent.mynotes')" width="800">
+            <div v-if="recordInfo">
+                <img :src="item" alt="" v-for="(item, index) in recordInfo.myNote" :key="index" style="width: 100%">
+            </div>
+        </Modal>
+        <Modal v-model="showWorks" :title="$t('studentWeb.courseContent.mynotes')" width="800" v-if="recordInfo">
+            <myWorks :recordInfo="recordInfo" :rcvData="myWorks" />
+        </Modal>
+    </div>
+</template>
+
+<script>
+import { mapGetters, mapState } from 'vuex'
+import BlobTool from "@/utils/blobTool.js"
+import videojs from "video.js";
+import "videojs-markers";
+
+import RcdPoster from '../../../view/homepage/RcdPoster.vue';
+import Loading from '@/common/Loading.vue';
+import DataCount from './newDataCount.vue';
+import ShowQues from './ShowQues.vue';
+import PopQues from '@/view/classrecord/eventchart/PopQues.vue';
+import Buzr from './Buzr.vue';
+import Push from '@/view/classrecord/eventchart/Push.vue';
+import StuReceive from './StuReceive.vue';
+import ReceiveBack from './ReceiveBack.vue';
+import Pick from './Pick.vue';
+import Exam from './Exam.vue';
+import myWorks from './myWorks.vue';
+
+export default {
+    components: {
+        RcdPoster,
+        Loading,
+        DataCount, ShowQues, PopQues, Buzr, Push,
+        StuReceive, ReceiveBack, Pick, Exam, myWorks,
+    },
+    data () {
+        return {
+            MyNo: "10",
+            MyName: this.$t('studentWeb.courseContent.classRecord'),
+            isLoad: false,
+            recordList: [],
+            continuationToken: null,
+            sasInfo: undefined,
+            nowIndex: -1,
+            
+            pageList: [], //课件
+            showPageList: [],
+            markers: [], //打点
+            playerOptions: {
+                height: "450px",
+                controlBar: {
+                    children: [// 写在这里,会在播放条上显示出来,并且是按照写的顺序显示位置。
+                        { name: "playToggle" }, //播放暂停按钮
+                        { name: "currentTimeDisplay" }, //当前播放时间
+                        { name: "progressControl" }, //播放进度条
+                        { name: "durationDisplay" }, //总时间
+                        {
+                            name: "playbackRateMenuButton",
+                            playbackRates: [0.5, 1, 1.5, 2, 2.5]
+                        }, //播放速率
+                        {
+                            name: "volumePanel", //音量控制
+                            inline: false, //不使用水平方式
+                        },
+                        { name: "FullscreenToggle" }, //全屏
+                        { name: "DashBoardEchart" }
+                    ],
+                },
+                /* html5: {
+                    nativeControlsForTouch: true,
+                }, */
+                // inactivityTimeout: 1,
+                // nativeVideoTracks: false,
+                // playbackRates: [0.5, 1.0, 1.25, 2.0], //播放速度
+                // autoplay: false, //如果true,浏览器准备好时开始回放。
+                controls: true, //控制条
+                preload: 'auto', //视频预加载
+                muted: false, //默认情况下将会消除任何音频。
+                // loop: false, //导致视频一结束就重新开始。
+                // language: 'zh-CN',
+                // aspectRatio: '16:9', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
+                //fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
+                sources: [{
+                    src: ""
+                }],
+                // notSupportedMessage: '此视频暂无法播放,请稍后再试' //允许覆盖Video.js无法播放媒体源时显示的默认信息。
+            },
+            curPage: 1, //当前课件页码
+            sokratesRecords: {}, //原始数据
+            recordInfo: undefined,
+            baseData: undefined, //base.json
+            pushData: [], //push.json
+            irsData: [], //irs.json
+            taskData: [], //task.json
+            fnEvents: [], //功能事件
+            events: [], //事件ID
+            hiTeachEvent: [], //需要解析的事件信息
+            isShowVd: true,
+            hasVideo: true,
+            showNote: false,
+            showWorks: false,
+            attendType: 2,
+            attentColor: ['', '#19be6b', '#EB3941', '#EB3941', '#EB3941', '#EB3941'],
+            nowStuInfo: undefined, //当前学生的信息
+            filtertype: {
+                push: 0, //推送
+                task: 0, //任务
+                irs: 0, //互动
+                exam: 0, //测验
+            },
+            myWorks: [],
+            haveInteraction: true,
+            player: undefined,
+            currentfilterType: "",
+        }
+    },
+    created () {
+        this.$emit("onNavNo", this.MyNo);
+        this.$emit("onNavName", this.MyName);
+        this.$store.commit("ToggleSidebar", true);
+        this.hiTeachEvent = this.$GLOBAL.HI_TEACH_EVENT()
+        this.events = Object.keys(this.hiTeachEvent)
+        this.fnEvents = this.events.filter(key => this.hiTeachEvent[key].type === 'fn')
+    },
+    mounted () {
+        // if(this.getNowCourse) {
+            this.getSas()
+            this.getRecordList()
+        // }
+        // this.getRecordList()
+    },
+    methods: {
+        async getSas() {
+            let code = this.courseNow.scope === "school" ? this.courseNow.school : this.courseNow.roster.teacherId
+            this.sasInfo = await this.$tools.getBlobSas(code)
+        },
+        getRecordList() {
+            let param = {
+                tmdid: this.courseNow.roster.teacherId,
+                scope: this.courseNow.scope, //school:传school,private:传tmdid
+                school: "",
+                category: [],
+                subjectId: [],
+                courseId: this.courseNow.id,
+                grade: [],
+                doubleGreen: false,
+                quality: false,
+                DESC: "startTime",
+                pageCount: 10, //返回六条数据(分页)
+                today: false,
+                continuationToken: this.continuationToken, //返回的有值的话,下次查询就要用这个值
+                groupIds: [this.courseNow.list],
+            }
+            param.scope === "school" ? param.school = this.courseNow.school : param.tmdid = this.courseNow.roster.teacherId
+            this.$api.studentWeb.getClassRecord(param).then(res => {
+                if(res.lessonRecords && res.lessonRecords.length) {
+                    let newList = res.lessonRecords.map(item => {
+                        item.startTime = this.dateFormat(item.startTime)
+                        let sec = item.duration % 60
+                        let min = parseInt(item.duration / 60)
+                        let mins = min >= 60 ? min % 60 : min
+                        let hour = parseInt(min / 60)
+                        item.time = `${hour < 10 ? ('0' + hour) : hour}:${mins < 10 ? ('0' + mins) : mins}:${sec < 10 ? ('0' + sec) : sec}`
+                        item.eNote = `${this.sasInfo.url}/${this.sasInfo.name}/records/${item.id}/Note.pdf?${this.sasInfo.sas}`
+                        item.CoverImage = `${this.sasInfo.url}/${this.sasInfo.name}/records/${item.id}/Record/CoverImage.jpg?${this.sasInfo.sas}`
+                        item.myNote = []
+                        return item
+                    })
+                    this.recordList.push.apply(this.recordList, newList)
+                    this.continuationToken = res.continuationToken
+                    this.getTrainFiles()
+                }
+            }).finally(() => {
+            })
+        },
+        // 查找活动的视频和文件
+        getTrainFiles() {
+            let blobTool = new BlobTool(this.sasInfo.url, this.sasInfo.name, "?" + this.sasInfo.sas, this.courseNow.scope)
+            let promiseArr = []
+            let recList = [...this.recordList]
+            recList.forEach((item, index) => {
+                promiseArr.push(new Promise((r, j) => {
+                    blobTool.listBlob({
+                        prefix: `records/${item.id}/Clients/${this.userInfo.sub}/Task/NoteSelfNote`
+                    }).then(
+                        res => {
+                            let imgList = []
+                            res.blobList.forEach(list => {
+                                imgList.push(`${list.url}?${this.sasInfo.sas}`)
+                            })
+                            this.recordList[index].myNote = imgList
+                            r(res)
+                        },
+                        err => {
+
+                        }
+                    )
+                }))
+            })
+            Promise.all(promiseArr).then(res => {
+                if(this.$route.query.aId) {
+                    let info = this.recordList.findIndex(item => {
+                        return item.id === this.$route.query.aId
+                    })
+                    if(info != -1) {
+                        this.toClassRecord(this.recordList[info], info)
+                    } else {
+                        this.$Message.warning("未找到课堂记录")
+                    }
+                } else {
+                    this.toClassRecord(this.recordList[0], 0)
+                }
+            })
+        },
+        handleReachTop () {
+            return new Promise(resolve => {
+                setTimeout(() => {
+                    if(this.continuationToken) {
+                        this.getRecordList()
+                    } else {
+                        this.$Message.warning("没有更多数据")
+                    }
+                    resolve()
+                }, 2000);
+            });
+        },
+        toClassRecord(item, index) {
+            this.recordInfo = []
+            this.nowIndex = index
+            this.recordInfo = {...item}
+            this.getPageList()
+            
+            ////螢幕寬度<767px時,直接關掉sidebar
+            if (window.innerWidth <= 1024) {
+                this.$store.commit("ToggleSidebar", false);
+            }
+        },
+        uploadNote(info, mine) {
+            // mine:我的笔记
+            if(mine) {
+                this.$tools.generatePdfByImgs(info.myNote, `${info.name}-${this.$t('studentWeb.courseContent.mynotes')}`)
+            } else {
+                this.$tools.doDownloadByUrl(info.eNote, info.name)
+            }
+        },
+        //查看电子笔记
+        async viewENote() {
+            let eNote
+            if (this.recordInfo.eNote) {
+                eNote = this.recordInfo.eNote
+            } else {
+                // let sasInfo = {}
+                // let blobInfo = this.recordInfo.scope === 'school' ? this.$store.state.user.schoolProfile : this.$store.state.user.userProfile
+                // sasInfo.sas = '?' + blobInfo.blob_sas
+                // sasInfo.name = this.recordInfo.scope ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId
+                // sasInfo.url = blobInfo.blob_uri.slice(0, blobInfo.blob_uri.lastIndexOf(sasInfo.name) - 1)
+                let sasInfo = await this.$tools.getBlobSas(this.recordInfo.scope === 'school' ? this.recordInfo.school : this.recordInfo.tmdid)
+                eNote = `${sasInfo.url}/${sasInfo.name}/records/${this.recordInfo.id}/Note.pdf?${sasInfo.sas}`
+            }
+            window.open('/web/viewer.html?file=' + encodeURIComponent(eNote))
+            // if (this.recordInfo.eNote) {
+            //     window.open('/web/viewer.html?file=' + encodeURIComponent(this.recordInfo.eNote))
+            // } else {
+            //     this.$Message.warning(this.$t('cusMgt.rcd.noNote'))
+            // }
+        },
+        // 根据SokratesRecords.json处理page数据
+        async getPageList() {
+            this.isLoad = true
+            this.pageList = []
+            this.showPageList = []
+            this.markers = []
+            let sas = await this.$tools.getBlobSas(this.recordInfo.scope === 'school' ? this.recordInfo.school : this.recordInfo.tmdid)
+            this.recordInfo.eNote = `${sas.url}/${sas.name}/records/${this.recordInfo.id}/Note.pdf?${sas.sas}`
+            // 如果只会存在一个视频,文件名是否可以固定?
+            this.playerOptions.sources[0].src = `${sas.url}/${sas.name}/records/${this.recordInfo.id}/Record/CourseRecord.mp4?${sas.sas}`
+            // let url = `${sas.url}/${sas.name}/records/${this.recordInfo.id}/Sokrates/SokratesRecords.json?${sas.sas}` //后面会根据TimeLine.json处理
+            // 这里需要兼容原来没有TimeLine.json的课例(优先度读timeLine.json,没有则读SokratesRecords.json)
+            let url = `${sas.url}/${sas.name}/records/${this.recordInfo.id}/IES/TimeLine.json?${sas.sas}`
+            let hasTimeLine = true
+            let dataErr = false
+            let pgids = []
+            let pageEvents = []
+            try {
+                let res = await this.$tools.getFile(url)
+                this.sokratesRecords = JSON.parse(res)
+                pgids = this.sokratesRecords.PgIdList || []
+                pageEvents = this.sokratesRecords.events || []
+            } catch (e) {
+                hasTimeLine = false
+            }
+            //读取 timeLine.json 失败,则读取 SokratesRecords.json
+            if (!hasTimeLine) {
+                url = `${sas.url}/${sas.name}/records/${this.recordInfo.id}/Sokrates/SokratesRecords.json?${sas.sas}`
+                try {
+                    let res = await this.$tools.getFile(url)
+                    let resJson = JSON.parse(res)
+                    // 处理成timeLine数据格式
+                    let pageidEvent = resJson.find(item => item.Event == 'PgidList')
+                    pgids = pageidEvent && pageidEvent.PgIdList ? pageidEvent.PgIdList : []
+                    pageEvents = resJson.filter(item => this.events.includes(item.Event))
+                    this.sokratesRecords = {
+                        events: pageEvents,
+                        PgIdList: pgids
+                    }
+                } catch (e) {
+                    //timeLine 和 SokratesRecords都没有找到
+                    dataErr = true
+                }
+            }
+            
+            // 数据异常
+            if (dataErr) {
+                this.$Message.error(this.$t('cusMgt.rcd.dataErr'))
+                return
+            }
+            //获取Push.json、IRS.json、Task.json、Base.json数据
+            try {
+                let pushUrl = `${sas.url}/${sas.name}/records/${this.recordInfo.id}/IES/Push.json?${sas.sas}`
+                this.pushData = JSON.parse(await this.$tools.getFile(pushUrl) || '[]')
+                this.pushData.forEach(item => {
+                    item.pageUrl = `${sas.url}/${sas.name}/records/${this.recordInfo.id}${item.pageMeta}?${sas.sas}`
+                })
+            } catch (e) {
+                this.pushData = []
+            }
+            try {
+                let irsUrl = `${sas.url}/${sas.name}/records/${this.recordInfo.id}/IES/IRS.json?${sas.sas}`
+                this.irsData = JSON.parse(await this.$tools.getFile(irsUrl) || '[]')
+            } catch (e) {
+                this.irsData = []
+            }
+            try {
+                let taskUrl = `${sas.url}/${sas.name}/records/${this.recordInfo.id}/IES/Task.json?${sas.sas}`
+                this.taskData = JSON.parse(await this.$tools.getFile(taskUrl) || '[]')
+            } catch (e) {
+                this.taskData = []
+            }
+            try {
+                let baseUrl = `${sas.url}/${sas.name}/records/${this.recordInfo.id}/IES/base.json?${sas.sas}`
+                this.baseData = JSON.parse(await this.$tools.getFile(baseUrl) || '{}')
+                this.baseData.student.forEach((item, index) => {
+                    if (item.id === this.userInfo.sub) {
+                        this.nowStuInfo = item
+                        this.nowStuInfo.index = index
+                    }
+                })
+                if(this.nowStuInfo) {
+                    let nowClient = this.baseData.report.clientSummaryList.find(item => {
+                        return this.nowStuInfo.seatID === item.seatID
+                    })
+                    this.attendType = nowClient ? nowClient.attendState : 2
+                }
+            } catch (e) {
+                this.baseData = undefined
+            }
+
+            //这里需要判断录制开始的pageid
+            let startInfo = pageEvents.find(item => item.Event === 'EzsStartRecord')
+            let startId = startInfo ? startInfo.Pgid : ''
+            let startIndex = 0
+            if (startId) {
+                startIndex = pgids.findIndex(item => item === startId)
+            }
+            pgids = pgids.slice(startIndex)
+
+            let havePage = 0
+            let myTask = []
+            pgids.forEach((item, index) => {
+                let page = {}
+                page.id = item
+                page.img = `${sas.url}/${sas.name}/records/${this.recordInfo.id}/Memo/${item}.jpg?${sas.sas}`
+                page.page = index + 1
+                //当前页面对应的sokrates
+                page.pageData = pageEvents.filter(record => record.Pgid === item && this.fnEvents.includes(record.Event))
+                havePage += (page.pageData.length ? 1 : 0)
+                page.pageData.forEach(e => {
+                    e.pageIndex = index
+                    e.eventName = this.hiTeachEvent[e.Event]?.text
+                    let rlt = this.hiTeachEvent[e.Event]?.relation
+                    e.relation = rlt
+                    switch (rlt) {
+                        case 'irs':
+                            this.filtertype.irs += 1
+                            e.data = this.irsData.find(i => i.pageID == e.Pgid)
+                            break
+                        case 'push':
+                            this.filtertype.push += 1
+                            e.data = this.pushData.find(p => p.pageId == e.Pgid || p.pageID == e.Pgid)
+                            break
+                        case 'task':
+                            this.filtertype.task += 1
+                            e.data = this.taskData.find(t => t.pageID == e.Pgid)
+                            myTask.push(e.data)
+                            break
+                        case 'timeline':
+                            e.data = this._.cloneDeep(e)
+                            break
+                        case 'exam':
+                            this.filtertype.exam += 1
+                            e.data = this._.cloneDeep(e)
+                            break
+                        default:
+                            break
+                    }
+                })
+                this.pageList.push(page)
+            })
+            if(this.baseData) {
+                myTask.forEach(item => {
+                    if(item && item.clientWorks.length) {
+                        item.clientWorks.forEach(works => {
+                            let owner = this.baseData.student.find(stu => stu.seatID == works.seatID && stu.id === this.$store.state.userInfo.sub)
+                            if(owner) {
+                                this.myWorks.push({
+                                    jobName: item.jobName,
+                                    collateType: item.collateType,
+                                    blobFiles: works.blobFiles
+                                })
+                            }
+                        })
+                    }
+                })
+            }
+            this.showPageList = [...this.pageList]
+            this.haveInteraction = havePage != 0
+            let pageEvent = pageEvents.filter(item => item.Event === 'PopQuesLoad' || item.Event === 'ReAtmpAnsStrt' || item.Event === 'FastPgPush' || item.Event === 'WrkSpaceLoad' || item.Event === 'SPQStrt')
+            this.markers = pageEvent.map((item, index) => {
+                return {
+                    time: item.Time,
+                    text: `${this.$t('cusMgt.rcd.di')}${index + 1}${this.$t('cusMgt.rcd.page')}`,
+                    page: index + 1
+                }
+            })
+            if(this.hasVideo) {
+                this.getVideo()
+            } else {
+                this.isLoad = false
+            }
+        },
+        getVideo() {
+            var that = this
+            this.player = videojs(document.getElementById('recordVideo' + this.recordInfo.id), this.playerOptions, function () {
+                this.on('error', (e) => {
+                    that.hasVideo = false
+                    that.isShowVd = false
+                })
+            })
+            //时间切片
+            /* this.player.markers({
+                markerStyle: {
+                    width: "16px",
+                    height: "16px",
+                    top: "-22px",
+                    "display": "inline-block",
+                    "border-radius": "50%",
+                    "font-size": "12px",
+                    "line-height": "16px",
+                    "background-color": "orange"
+                },
+                breakOverlay: {
+                    display: false,
+                    displayTime: 4,
+                    style: {
+                        "z-index": "6",
+                        width: "100%",
+                        height: "10%",
+                        "background-color": "rgba(200,250,10,0.6)",
+                        color: "white",
+                        "font-size": "16px",
+                    },
+                    text: function (marker) {
+                        return that.$t('system.compt.cusWare') + marker.text;
+                    },
+                },
+                markerTip: {
+                    display: false,
+                    text: function (marker) {
+                        return marker.text;
+                    },
+                },
+                markers: that.markers,
+
+                //标记点击事件
+                onMarkerClick: function (marker) {
+
+                },
+                //视频播放到标记点触发的时间
+                onMarkerReached: function (marker) {
+                    let mkDoms = document.getElementsByClassName('vjs-marker ')
+                    for (let index in mkDoms) {
+                        if (mkDoms[index].dataset) {
+                            if (parseInt(mkDoms[index].dataset.markerTime) <= marker.time) {
+                                mkDoms[index].style.backgroundColor = '#1CC0F3'
+                                mkDoms[index].classList.add('vjs-marker-active')
+                            } else {
+                                mkDoms[index].style.backgroundColor = 'orange'
+                                mkDoms[index].classList.remove('vjs-marker-active')
+                            }
+                            // mkDoms[index].innerHTML = this.markers[index].page
+                        }
+                    }
+                    that.getCurPage(marker.page)
+                },
+            }); */
+
+            this.isLoad = false
+        },
+        // 点击视频切片
+        getCurPage(page) {
+            this.curPage = page
+            // this.mapJson = require('./data/' + page + '.json')
+            // this.$refs["datawrap"].scrollIntoView('#page' + page, 500)
+            this.player.play()
+        },
+        // 点击课件page
+        getCurHTEX(page) {
+            this.curPage = page
+            // this.mapJson = require('./data/' + page + '.json')
+            //视频时间定位
+            let pageInfo = this.markers.find(item => {
+                return item.page === page
+            })
+            if (pageInfo) {
+                this.player.currentTime(pageInfo.time)
+                if (!this.openHtexViewer) {
+                    this.player.play()
+                } else {
+                    this.player.pause()
+                }
+                //互动记录滚动
+                // this.$refs["datawrap"].scrollIntoView('#page' + page, 500)
+            } else {
+            }
+        },
+        filterFn(type) {
+            this.showPageList = []
+            if(type === 'all') {
+                this.showPageList = [...this.pageList]
+            } else {
+                this.isLoad = true
+                this.pageList.forEach(item => {
+                    if(item.pageData.length) {
+                        let filterArr = item.pageData.filter(data => {
+                            return data.relation === type
+                        })
+                        if(filterArr.length) {
+                            this.showPageList.push({
+                                id: item.id,
+                                img: item.img,
+                                page: item.page,
+                                pageData: filterArr
+                            })
+                        }
+                    }
+                })
+                this.isLoad = false
+            }
+        },
+        dateFormat(timestamp) {
+            var date = new Date(timestamp)
+            var Y = date.getFullYear() + '-'
+            var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-'
+            var D = (date.getDate() < 10 ? '0' + (date.getDate()) : date.getDate()) + ' '
+            var H = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ":"
+            var Min = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes())
+            var S = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()) + " "
+            return Y + M + D + H + Min;
+        },
+    },
+    computed: {
+        ...mapGetters(["getNowCourse", "getSidebarisOpen",]),
+        ...mapState({
+            userInfo: state => state.userInfo,
+        }),
+        curImg() {
+            if (this.pageList[this.curPage - 1]) {
+                return this.pageList[this.curPage - 1].img
+            } else {
+                return ""
+            }
+        },
+        courseNow() {
+            return this.getNowCourse || JSON.parse(decodeURIComponent(localStorage.course, "utf-8"))
+        },
+    },
+}
+</script>
+
+<style lang="less" scoped>
+@import "./RecordView.less";
+</style>
+
+<style lang="less">
+.record-view-right {
+    .video-js .vjs-big-play-button {
+        top: 50%;
+        left: 50%;
+        margin-left: -20px;
+        margin-top: -20px;
+        display: none;
+    }
+
+    .video-js .vjs-control-bar {
+        display: flex;
+    }
+
+    .vjs-marker::after {
+        content: "";
+        height: 0px;
+        width: 0px;
+        border: 3px transparent solid;
+        display: block;
+        position: absolute;
+        bottom: -10px;
+        z-index: -1;
+        border-right: 8px solid transparent;
+        border-top: 15px solid orange;
+        border-left: 8px solid transparent;
+    }
+    .vjs-marker-active::after {
+        border-right: 8px solid transparent !important;
+        border-top: 15px solid #1cc0f3 !important;
+        border-left: 8px solid transparent !important;
+    }
+
+    .vjs-marker:hover {
+        z-index: 101;
+    }
+
+
+    .ivu-btn-primary {
+        background-color: #24b880;
+        border-color: #24b880;
+
+        &:not(:last-child) {
+            margin-right: 15px;
+        }
+    }
+
+    .ivu-btn-warning {
+        color: #515a6e;
+        background-color: #FEE49E;
+        border-color: #FEE49E;
+
+        &:not(:last-child) {
+            margin-right: 15px;
+        }
+    }
+
+    .ivu-btn-primary[disabled],
+    .ivu-btn-primary[disabled]:hover {
+        background-color: #24b880;
+        border-color: #24b880;
+    }
+
+    .ivu-btn-warning[disabled],
+    .ivu-btn-warning[disabled]:hover {
+        color: #c5c8ce;
+        background-color: #FEE49E;
+        border-color: #FEE49E;
+    }
+}
+
+.owner-student-client-icon {
+    font-size: 30px;
+    padding: 5px;
+    color: #ffffff;
+    border-radius: 50%;
+    background: #de7320;
+}
+
+.scroll-list {
+    height: 100%;
+
+    .ivu-scroll-container {
+        height: 100% !important;
+    }
+}
+</style>

+ 2 - 2
TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/ShowQues.vue

@@ -79,7 +79,7 @@ export default {
         nowStuInfo: {
             type: Object,
             default: () => {
-                return {}
+                return undefined
             }
         }
     },
@@ -112,7 +112,7 @@ export default {
             immediate: true,
             handler(n, o) {
                 console.log(n)
-                if (n.clientAnswers && n.question) {
+                if (n.clientAnswers && n.question && this.nowStuInfo) {
                     this.answer = n.question?.exercise?.answer || []
                     let answerData
                     //单选题

+ 61 - 49
TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/newDataCount.vue

@@ -90,57 +90,69 @@ export default {
         }
     },
     created() {
-        if (this.rcdInfo) {
-            console.log(this.rcdInfo);
-            const summary = this.rcdInfo
-            let nowClient = summary.report.clientSummaryList.find(item => {
-                return this.nowStuInfo.seatID === item.seatID
-            })
-            if(nowClient) {
-                /* 
-                    EAttendState
-                    {
-                        Uncall,0(未點名)
-                        Attended,1(出席)
-                        Absent,2(缺席)
-                        DayOff,3(請假)
-                        Absent_Sick,4(病假)
-                        Absent_Personal,5(事假)
-                        Absent_Official,6(公假)
-                    }
-                */
-                this.attendType = nowClient.attendState
-                // this.dataList[0].value = nowClient.attendState
-                // 记分
-                this.dataList[0].value = nowClient.score
-                // 互动分
-                this.dataList[1].value = nowClient.interactScore
-                // 任务数
-                this.dataList[4].value = nowClient.taskCompleteCount
-                nowClient.examScoreList.map(item => {
-                    this.dataList2[2].value += item
+        this.getData(this.rcdInfo)
+    },
+    watch: {
+        rcdInfo: {
+            handler(n, o) {
+                this.getData(n)
+            },
+            deep: true,
+        }
+    },
+    methods: {
+        getData(info) {
+            if (info) {
+                const summary = {...info}
+                let nowClient = summary.report.clientSummaryList.find(item => {
+                    return this.nowStuInfo.seatID === item.seatID
                 })
+                if(nowClient) {
+                    /* 
+                        EAttendState
+                        {
+                            Uncall,0(未點名)
+                            Attended,1(出席)
+                            Absent,2(缺席)
+                            DayOff,3(請假)
+                            Absent_Sick,4(病假)
+                            Absent_Personal,5(事假)
+                            Absent_Official,6(公假)
+                        }
+                    */
+                    this.attendType = nowClient.attendState
+                    // this.dataList[0].value = nowClient.attendState
+                    // 记分
+                    this.dataList[0].value = nowClient.score
+                    // 互动分
+                    this.dataList[1].value = nowClient.interactScore
+                    // 任务数
+                    this.dataList[4].value = nowClient.taskCompleteCount
+                    nowClient.examScoreList.map(item => {
+                        this.dataList2[2].value += item
+                    })
+                }
+                // 出席
+                // this.dataList[0].value = summary.attendCount
+                // 總計分
+                // this.dataList[1].value = summary.totalPoint
+                // 總互動分
+                // this.dataList[2].value = summary.totalInteractPoint
+                // 任务总数(作品收集任務數)
+                // this.dataList[3].value = summary.collateTaskCount
+                // 作品总数
+                this.dataList[3].value = summary.report.collateCount
+                // 推送總數(頁面+資源+訊息+差異化)
+                this.dataList[4].value = summary.report.pushCount
+                // 测验总题数
+                this.dataList2[0].value = summary.report.examQuizCount
+                // 互动题数
+                this.dataList2[1].value = summary.report.interactionCount
+                // 测验得分率
+                // this.dataList[8].value = summary.examPointRate
+                this.$forceUpdate()
             }
-            // 出席
-            // this.dataList[0].value = summary.attendCount
-            // 總計分
-            // this.dataList[1].value = summary.totalPoint
-            // 總互動分
-            // this.dataList[2].value = summary.totalInteractPoint
-            // 任务总数(作品收集任務數)
-            // this.dataList[3].value = summary.collateTaskCount
-            // 作品总数
-            this.dataList[3].value = summary.report.collateCount
-            // 推送總數(頁面+資源+訊息+差異化)
-            this.dataList[4].value = summary.report.pushCount
-            // 测验总题数
-            this.dataList2[0].value = summary.report.examQuizCount
-            // 互动题数
-            this.dataList2[1].value = summary.report.interactionCount
-            // 测验得分率
-            // this.dataList[8].value = summary.examPointRate
-            this.$forceUpdate()
-        }
+        },
     }
 }
 </script>

+ 281 - 0
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/Homework.less

@@ -0,0 +1,281 @@
+@import '~@/assets/student-web/component_styles/color.less';
+
+.homework-content {
+    .uploadMessage {
+        margin-top: 20px;
+    }
+
+    .uploadSuccessIcon {
+        font-size: 70px;
+        margin: 5px auto;
+    }
+
+    .upload-item {
+        border: 1px solid gray;
+        padding: 10px 20px;
+        margin-bottom: 20px;
+        max-width: 100%;
+        border-radius: 4px;
+        white-space: nowrap;
+        cursor: pointer;
+        background-color: rgb(253, 253, 253);
+        position: relative;
+
+        li {
+            list-style: none;
+        }
+
+        &:hover {
+            background: @bgcHover;
+
+            .upload-item-icon,
+            .upload-item-info {
+                color: @titleHover  !important;
+            }
+
+            border: 1px solid @titleHover;
+        }
+
+        .upload-item-icon {
+            color: #515a6e;
+            text-align: center;
+            display: inline-block;
+            width: 25%;
+            font-size: 40px;
+            margin-left: -10px;
+        }
+
+        .upload-item-info {
+            color: #515a6e;
+            display: inline-block;
+            width: 70%;
+        }
+
+        .upload-item-name {
+            overflow: hidden;
+            white-space: nowrap;
+            text-overflow: ellipsis;
+            font-size: 14px;
+            font-weight: bolder;
+        }
+
+        .upload-item-time {
+            font-size: 10px;
+            color: rgb(146, 146, 146);
+        }
+
+        @media screen and (max-width: 1366px) {
+            .upload-item-icon {
+                width: 35%;
+            }
+        }
+
+        @media screen and (max-width: 767px) {
+            .upload-item-icon {
+                width: 13%;
+            }
+        }
+    }
+
+    .upload-item-selected {
+        background: @bgcHover;
+        color: @titleHover;
+        border: 2px solid @titleHover;
+
+        .upload-item-icon,
+        .upload-item-name {
+            color: @titleHover;
+        }
+    }
+
+    //評量成績報告的分頁組件
+    .ivu-tabs-nav {
+        float: left !important;
+        position: relative;
+        text-align: center;
+        z-index: 1;
+    }
+
+    .ivu-tabs-tab {
+        text-align: center !important;
+        font-size: 24px;
+        margin: 0px 10px;
+        width: auto;
+    }
+
+    .ivu-tabs-tab:hover {
+        text-align: center !important;
+        color: @primary  !important;
+    }
+
+    .homework .ivu-tabs-tab.ivu-tabs-tab-active.ivu-tabs-tab-focused {
+        color: @primary  !important;
+        font-weight: bolder;
+        border-bottom: 5px solid @primary  !important;
+        margin: 0px 10px;
+        width: auto;
+    }
+
+    .ivu-tabs-ink-bar {
+        height: 0px;
+    }
+
+    .ivu-tabs-tabpane {
+        margin-top: -16px;
+        overflow-x: hidden;
+        height: auto;
+    }
+
+    .homework-detail {
+        .answer-title {
+            font-weight: bold;
+            font-size: 20px;
+            margin-top: 10px;
+        }
+
+        .file-show {
+            background-color: #f1f1f1;
+            border-radius: 5px;
+            padding: 20px 25px;
+            margin-top: 10px;
+
+            .answer-show img {
+                max-width: 50% !important;
+            }
+
+            &>p {
+                font-size: 18px;
+                font-weight: bold;
+                margin-bottom: 10px;
+            }
+
+            /* .one-show{
+                display: flex;
+                justify-content: space-between;
+                padding: 0 5px 5px;
+                // padding-bottom: 5px;
+                margin-bottom: 10px;
+                // padding-left: 5px;
+                border-bottom: 1px solid #ccc;
+
+                .ivu-icon{
+                    cursor: pointer;
+                }
+            } */
+
+            .repair-link-wrap-item-box {
+                display: flex;
+                position: relative;
+                // background-color: #e3e3e3;
+                border-radius: 5px;
+                padding: 10px 0;
+                font-size: 14px;
+
+                &:hover {
+                    background-color: #ebe9e9;
+                }
+
+                .file-icon {
+                    img {
+                        width: 45px;
+                    }
+                }
+
+                .file-info {
+                    margin-left: 10px;
+
+                    .file-name {
+                        font-weight: bold;
+                        margin-bottom: 5px;
+                    }
+
+                    span {
+                        color: #16a3b5;
+                        margin-right: 15px;
+                        cursor: pointer;
+                    }
+                }
+            }
+        }
+
+        .home-upload {
+            display: flex;
+            margin-bottom: 10px;
+
+            .uploadBtn {
+                padding: 3px 15px;
+            }
+        }
+
+        .myProgressBar {
+            width: 100%;
+            padding-top: 2px;
+
+            .myTestProgressContent {
+                position: relative;
+                background: rgb(192, 192, 192);
+                margin-top: 5px;
+                height: 8px;
+                border-radius: 4px;
+            }
+
+            .myTestProgress {
+                height: 8px;
+                animation: 2s widthborn ease-in;
+                position: relative;
+                top: -8px;
+                background: @primary;
+                border-radius: 4px;
+            }
+        }
+
+        @keyframes widthborn {
+            0% {
+                width: 0%;
+            }
+
+            100% {
+                width: 100%;
+            }
+        }
+
+        .uploading-item-icon {
+            position: relative;
+        }
+
+        .uploading-item-info {
+            position: relative;
+            top: -12px;
+        }
+    }
+
+    .image-viewer {
+        background-color: rgba(0, 0, 0, 0.8);
+        z-index: 9999;
+        width: 100%;
+        height: 100%;
+        position: fixed;
+        top: 0;
+        left: 0;
+        overflow-y: scroll;
+        overflow-x: hidden;
+        text-align: center;
+        /*display: flex;
+        justify-content: center;
+        align-items: center;*/
+        padding: 50px;
+        padding-top: 8%;
+
+        .close-icon {
+            position: absolute;
+            right: -16px;
+            top: -16px;
+            font-size: 24px;
+            color: black;
+            cursor: pointer;
+            border-radius: 50px;
+            background: white;
+            padding: 2px;
+        }
+    }
+}

+ 174 - 214
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/Homework.vue

@@ -1,5 +1,5 @@
 <template>
-    <div class="homework">
+    <div class="event-content">
         <div v-if="openLightBox" class="lightBox">
             <Icon class="ImgCloseIcon" type="md-close" @click="closeImg()" />
             <div v-for="(item, index) in getItemTitle.imgList"
@@ -18,203 +18,205 @@
             </button>
         </div>
 
-        <EventBasicInfo :info="getItemTitle" />
         <Loading v-show="isLoad" bgColor="rgba(0, 0, 0, 0.3)"></Loading>
-        
-        <!-- 已交作业 -->
-        <Tabs :value="selectTab" @on-click="onTabChange">
-            <!-- 作业内容 -->
-            <TabPane :label="$t('studentWeb.homework.contentPage')" name="homework">
-                
-                <!-- 时间到 -->
-                <div v-if="homeworkInfo && isEnd && !isApply && !answerList">
-                    <div class="dec animate__animated animate__bounceInLeft">
-                        <svg-icon icon-class="handonHint" class="warm-icon" />
-                        <span class="warm-hint">{{ $t("studentWeb.homework.timeoutHint") }}</span>
+        <vuescroll>
+            <EventBasicInfo :info="getItemTitle" />
+            
+            <!-- 已交作业 -->
+            <Tabs :value="selectTab" @on-click="onTabChange" class="homework-content">
+                <!-- 作业内容 -->
+                <TabPane :label="$t('studentWeb.homework.contentPage')" name="homework">
+                    
+                    <!-- 时间到 -->
+                    <div v-if="homeworkInfo && isEnd && !isApply && !answerList">
+                        <div class="dec animate__animated animate__bounceInLeft">
+                            <svg-icon icon-class="handonHint" class="warm-icon" />
+                            <span class="warm-hint">{{ $t("studentWeb.homework.timeoutHint") }}</span>
+                        </div>
                     </div>
-                </div>
-                <!-- 补交 -->
-                <div v-if="homeworkInfo && isEnd && isApply && (!answerList || answerList.time > homeworkInfo.endTime)">
-                    <div class="dec animate__animated animate__bounceInLeft">
-                        <svg-icon icon-class="handonHint" class="warm-icon" />
-                        <span class="warm-hint">{{ $t("studentWeb.homework.timeoutApply") }}</span>
+                    <!-- 补交 -->
+                    <div v-if="homeworkInfo && isEnd && isApply && (!answerList || answerList.time > homeworkInfo.endTime)">
+                        <div class="dec animate__animated animate__bounceInLeft">
+                            <svg-icon icon-class="handonHint" class="warm-icon" />
+                            <span class="warm-hint">{{ $t("studentWeb.homework.timeoutApply") }}</span>
+                        </div>
                     </div>
-                </div>
 
-                <div class="homework-detail" v-if="homeworkInfo">
-                    <BillBoardandLightBox :activityData="homeworkInfo" />
-                    <div>
-                        <!-- 附件 -->
-                        <div v-if="homeworkInfo.attachments.length">
-                            <div class="title-rect-group">
-                                <h2 class="title-rect-name">{{$t('studentWeb.billboard.attachment')}}</h2>
-                            </div>
-                            <!-- <Table :columns="fileCol" :data="homeworkInfo.attachments">
-                                <template slot-scope="{row}" slot="action">
-                                    <Icon type="md-download" size="20" @click="loadAttach(row)" :title="$t('studentWeb.homework.upload')" />
-                                </template>
-                            </Table> -->
-                            <div class="file-show">
-                                <div v-for="(item, index) in homeworkInfo.attachments" :key="index" class="one-show">
-                                    <div class="repair-link-wrap-item-box">
-                                        <div class="file-icon">
-                                            <img :src="$tools.getFileThum(item.type, item.name)"/>
-                                        </div>
-                                        <div class="file-info">
-                                            <p class="file-name">{{ item.name }}</p>
-                                            <div>
-                                                <span @click="onPreview(item)" v-if="item.type !== 'other'">{{ $t('ability.review.preview')}}</span>
-                                                <span @click="onDownload(item)" v-if="item.type !== 'link'">{{ $t('ability.review.download')}}</span>
+                    <div class="homework-detail" v-if="homeworkInfo">
+                        <BillBoardandLightBox :activityData="homeworkInfo" />
+                        <div>
+                            <!-- 附件 -->
+                            <div v-if="homeworkInfo.attachments.length">
+                                <div class="title-rect-group">
+                                    <h2 class="title-rect-name">{{$t('studentWeb.billboard.attachment')}}</h2>
+                                </div>
+                                <!-- <Table :columns="fileCol" :data="homeworkInfo.attachments">
+                                    <template slot-scope="{row}" slot="action">
+                                        <Icon type="md-download" size="20" @click="loadAttach(row)" :title="$t('studentWeb.homework.upload')" />
+                                    </template>
+                                </Table> -->
+                                <div class="file-show">
+                                    <div v-for="(item, index) in homeworkInfo.attachments" :key="index" class="one-show">
+                                        <div class="repair-link-wrap-item-box">
+                                            <div class="file-icon">
+                                                <img :src="$tools.getFileThum(item.type, item.name)"/>
+                                            </div>
+                                            <div class="file-info">
+                                                <p class="file-name">{{ item.name }}</p>
+                                                <div>
+                                                    <span @click="onPreview(item)" v-if="item.type !== 'other'">{{ $t('ability.review.preview')}}</span>
+                                                    <span @click="onDownload(item)" v-if="item.type !== 'link'">{{ $t('ability.review.download')}}</span>
+                                                </div>
                                             </div>
                                         </div>
                                     </div>
                                 </div>
                             </div>
-                        </div>
-                        <!-- 已交作业 -->
-                        <div v-if="answerList">
-                            <div class="title-rect-group">
-                                <h2 class="title-rect-name">{{ $t('studentWeb.homework.homeworkShow') }}</h2>
-                            </div>
-                            <!-- <p style="margin-top: 10px">上传时间:{{ answerList[0].time }}</p> -->
-                            
-                            <!-- 同学作业观摩互评 -->
-                            <!-- <div class="home-upload">
-                                <div v-if="homeworkInfo.allowComment && answerList && homeworkInfo.progress == 'finish'"
-                                    class="uploadBtn" @click="openComment()"
-                                >
-                                    <Icon type="ios-eye-outline" class="uploadBtn-icon" />
-                                    <span>{{ $t("studentWeb.homework.CommentClassmatesHomeworkBtn") }}</span>
+                            <!-- 已交作业 -->
+                            <div v-if="answerList">
+                                <div class="title-rect-group">
+                                    <h2 class="title-rect-name">{{ $t('studentWeb.homework.homeworkShow') }}</h2>
                                 </div>
-                            </div> -->
-                            <div v-if="answerList.answer" style="margin-bottom: 15px;">
-                                <p class="answer-title">{{ $t("studentWeb.homework.content") }}:</p>
-                                <div class="file-show">
-                                    <p v-html="answerList.answer" class="answer-show"></p>
-                                </div>
-                            </div>
-                            <div v-if="answerList.content.length">
-                                <p class="answer-title">{{ $t("studentWeb.homework.attachment") }}:</p>
-                                <Table :columns="fileCol" :data="answerList.content">
-                                    <template slot-scope="{row}" slot="action">
-                                        <Icon type="md-download" size="20" @click="loadAttach(row)" :title="$t('studentWeb.homework.upload')" />
-                                    </template>
-                                </Table>
-                                <!-- <div class="file-show">
-                                    <div v-for="(item, index) in answerList.content" :key="index" class="one-show">
-                                        <p>{{ item.name }}</p>
-                                        <p>
-                                            <span style="margin-right: 20px">{{ $t('studentWeb.homework.uploadTime') }}:{{ item.time }}</span>
-                                            <Icon type="md-download" size="20" @click="loadAttach(item)" :title="$t('studentWeb.homework.upload')" />
-                                        </p>
+                                <!-- <p style="margin-top: 10px">上传时间:{{ answerList[0].time }}</p> -->
+                                
+                                <!-- 同学作业观摩互评 -->
+                                <!-- <div class="home-upload">
+                                    <div v-if="homeworkInfo.allowComment && answerList && homeworkInfo.progress == 'finish'"
+                                        class="uploadBtn" @click="openComment()"
+                                    >
+                                        <Icon type="ios-eye-outline" class="uploadBtn-icon" />
+                                        <span>{{ $t("studentWeb.homework.CommentClassmatesHomeworkBtn") }}</span>
                                     </div>
                                 </div> -->
-                            </div>
-                        </div>
-                        <!-- 作业上传 -->
-                        <div v-if="!isEnd || (isApply && (!answerList || answerList.time > homeworkInfo.endTime))">
-                            <div class="title-rect-group">
-                                <h2 class="title-rect-name">
-                                    {{ $t("studentWeb.homework.homeworkUpload") }}
-                                </h2>
-                            </div>
-                            <div class="file-show">
-                                <p>{{ $t("studentWeb.homework.fileArea") }}:</p>
-                                <div style="margin-bottom: 5px; font-size: 14px">
-                                    <p v-if="homeworkInfo.mustSubmit">
-                                        <Icon type="md-alert" color="#cc4343" />
-                                        {{ $t('studentWeb.homework.mustFile') }}
-                                    </p>
-                                    <p v-if="homeworkInfo.extLimit.length">
-                                        <Icon type="md-alert" color="#64ae16" />
-                                        {{ $t('studentWeb.homework.fileType') }}:
-                                        <span v-for="(item, index) in homeworkInfo.extLimit" :key="index" style="margin-right: 10px">.{{ item }}</span>
-                                    </p>
-                                    <p v-if="homeworkInfo.allowComment">
-                                        <Icon type="md-alert" color="#64ae16" />
-                                        {{ $t('studentWeb.homework.allowComment') }}
-                                    </p>
-                                    <p>
-                                        <Icon type="md-alert" color="#64ae16" />
-                                        {{ $t('studentWeb.homework.fileSize') }}:
-                                        <span style="margin-right: 10px">{{ $t('studentWeb.homework.maxSize') }}</span>
-                                    </p>
-                                </div>
-                                <div>
-                                    <div class="home-upload">
-                                        <div class="uploadBtn">
-                                            <Upload
-                                                multiple
-                                                action=""
-                                                :before-upload="customUpload"
-                                                :show-upload-list="false"
-                                                :accept="accept"
-                                            >
-                                                <div style="display: flex">
-                                                    <Icon type="md-cloud-upload" size="20" />
-                                                    <p style="margin-left: 10px">
-                                                        {{ $t("studentWeb.homework.homeworkChoice") }}
-                                                    </p>
-                                                </div>
-                                            </Upload>
-                                        </div>
+                                <div v-if="answerList.answer" style="margin-bottom: 15px;">
+                                    <p class="answer-title">{{ $t("studentWeb.homework.content") }}:</p>
+                                    <div class="file-show">
+                                        <p v-html="answerList.answer" class="answer-show"></p>
                                     </div>
+                                </div>
+                                <div v-if="answerList.content.length">
+                                    <p class="answer-title">{{ $t("studentWeb.homework.attachment") }}:</p>
+                                    <Table :columns="fileCol" :data="answerList.content">
+                                        <template slot-scope="{row}" slot="action">
+                                            <Icon type="md-download" size="20" @click="loadAttach(row)" :title="$t('studentWeb.homework.upload')" />
+                                        </template>
+                                    </Table>
                                     <!-- <div class="file-show">
-                                        <div v-for="(item, index) in uploadList" :key="index">
+                                        <div v-for="(item, index) in answerList.content" :key="index" class="one-show">
                                             <p>{{ item.name }}</p>
+                                            <p>
+                                                <span style="margin-right: 20px">{{ $t('studentWeb.homework.uploadTime') }}:{{ item.time }}</span>
+                                                <Icon type="md-download" size="20" @click="loadAttach(item)" :title="$t('studentWeb.homework.upload')" />
+                                            </p>
                                         </div>
                                     </div> -->
-                                    
+                                </div>
+                            </div>
+                            <!-- 作业上传 -->
+                            <div v-if="!isEnd || (isApply && (!answerList || answerList.time > homeworkInfo.endTime))">
+                                <div class="title-rect-group">
+                                    <h2 class="title-rect-name">
+                                        {{ $t("studentWeb.homework.homeworkUpload") }}
+                                    </h2>
+                                </div>
+                                <div class="file-show">
+                                    <p>{{ $t("studentWeb.homework.fileArea") }}:</p>
+                                    <div style="margin-bottom: 5px; font-size: 14px">
+                                        <p v-if="homeworkInfo.mustSubmit">
+                                            <Icon type="md-alert" color="#cc4343" />
+                                            {{ $t('studentWeb.homework.mustFile') }}
+                                        </p>
+                                        <p v-if="homeworkInfo.extLimit.length">
+                                            <Icon type="md-alert" color="#64ae16" />
+                                            {{ $t('studentWeb.homework.fileType') }}:
+                                            <span v-for="(item, index) in homeworkInfo.extLimit" :key="index" style="margin-right: 10px">.{{ item }}</span>
+                                        </p>
+                                        <p v-if="homeworkInfo.allowComment">
+                                            <Icon type="md-alert" color="#64ae16" />
+                                            {{ $t('studentWeb.homework.allowComment') }}
+                                        </p>
+                                        <p>
+                                            <Icon type="md-alert" color="#64ae16" />
+                                            {{ $t('studentWeb.homework.fileSize') }}:
+                                            <span style="margin-right: 10px">{{ $t('studentWeb.homework.maxSize') }}</span>
+                                        </p>
+                                    </div>
                                     <div>
-                                        <div style="margin-top: 15px" v-if="uploadList.length">
-                                            <Row :gutter="15">
-                                                <i-col :key="index" v-for="(item, index) in uploadList" :xs="24" :sm="24" :md="12" :lg="6">
-                                                    <div class="upload-item">
-                                                        <Icon type="md-close" size="18" @click="delUpload(index)" />
-                                                        <div class="upload-item-icon">
-                                                            <svg-icon icon-class="doc" />
-                                                        </div>
-                                                        <div class="upload-item-info">
-                                                            <li class="upload-item-name">
-                                                                {{ item.name }}
-                                                            </li>
-                                                        </div>
+                                        <div class="home-upload">
+                                            <div class="uploadBtn">
+                                                <Upload
+                                                    multiple
+                                                    action=""
+                                                    :before-upload="customUpload"
+                                                    :show-upload-list="false"
+                                                    :accept="accept"
+                                                >
+                                                    <div style="display: flex">
+                                                        <Icon type="md-cloud-upload" size="20" />
+                                                        <p style="margin-left: 10px">
+                                                            {{ $t("studentWeb.homework.homeworkChoice") }}
+                                                        </p>
                                                     </div>
-                                                </i-col>
-                                            </Row>
+                                                </Upload>
+                                            </div>
+                                        </div>
+                                        <!-- <div class="file-show">
+                                            <div v-for="(item, index) in uploadList" :key="index">
+                                                <p>{{ item.name }}</p>
+                                            </div>
+                                        </div> -->
+                                        
+                                        <div>
+                                            <div style="margin-top: 15px" v-if="uploadList.length">
+                                                <Row :gutter="15">
+                                                    <i-col :key="index" v-for="(item, index) in uploadList" :xs="24" :sm="24" :md="12" :lg="6">
+                                                        <div class="upload-item">
+                                                            <Icon type="md-close" size="18" @click="delUpload(index)" />
+                                                            <div class="upload-item-icon">
+                                                                <svg-icon icon-class="doc" />
+                                                            </div>
+                                                            <div class="upload-item-info">
+                                                                <li class="upload-item-name">
+                                                                    {{ item.name }}
+                                                                </li>
+                                                            </div>
+                                                        </div>
+                                                    </i-col>
+                                                </Row>
+                                            </div>
                                         </div>
                                     </div>
                                 </div>
-                            </div>
-                            <div class="file-show">
-                                <p>{{ $t("studentWeb.homework.answerArea") }}:</p>
-                                <div>
+                                <div class="file-show">
+                                    <p>{{ $t("studentWeb.homework.answerArea") }}:</p>
                                     <div>
-                                        <Compose ref="compose" :itemInfo="homeworkInfo" :close="false" :textData="hwText" :index="0" @dataGet="getComposeAns"></Compose>
-                                        <!-- <Input v-special-char v-model="hwText" type="textarea" :rows="4" :placeholder="$t('studentWeb.homework.placeholder1')" /> -->
+                                        <div>
+                                            <Compose ref="compose" :itemInfo="homeworkInfo" :close="false" :textData="hwText" :index="0" @dataGet="getComposeAns"></Compose>
+                                            <!-- <Input v-special-char v-model="hwText" type="textarea" :rows="4" :placeholder="$t('studentWeb.homework.placeholder1')" /> -->
+                                        </div>
                                     </div>
                                 </div>
+                                <Button size="large" type="success" @click="submitHome" style="margin-top: 20px">
+                                    <svg-icon icon-class="doc" />
+                                    <span style="margin-left:5px">
+                                        {{ !answerList ? $t("studentWeb.homework.homeworkUoloadBtn") : $t("studentWeb.homework.homeworkReUoloadBtn") }}
+                                    </span>
+                                </Button>
                             </div>
-                            <Button size="large" type="success" @click="submitHome" style="margin-top: 20px">
-                                <svg-icon icon-class="doc" />
-                                <span style="margin-left:5px">
-                                    {{ !answerList ? $t("studentWeb.homework.homeworkUoloadBtn") : $t("studentWeb.homework.homeworkReUoloadBtn") }}
-                                </span>
-                            </Button>
+                            <!-- <p class="uploadMessage">{{ uploadMessage }}</p> -->
                         </div>
-                        <!-- <p class="uploadMessage">{{ uploadMessage }}</p> -->
                     </div>
-                </div>
-            </TabPane>
-            <!-- 成绩评语 -->
-            <TabPane :label="$t('studentWeb.homework.scorePage')" name="score" v-if="answerList && (answerList.comments.length || isEnd)">
-                <HomeworkFeedback :homeWork="homeworkInfo" />
-            </TabPane>
-            <!-- 互评 -->
-            <TabPane :label="$t('studentWeb.homework.classComment')" name="classComment" v-if="homeworkInfo && homeworkInfo.allowComment && answerList && isEnd && students.length">
-                <ClassmateCommentPages :homeWork="homeworkInfo" :students="students" @onPreview="onPreview" />
-            </TabPane>
-        </Tabs>
+                </TabPane>
+                <!-- 成绩评语 -->
+                <TabPane :label="$t('studentWeb.homework.scorePage')" name="score" v-if="answerList && (answerList.comments.length || isEnd)">
+                    <HomeworkFeedback :homeWork="homeworkInfo" />
+                </TabPane>
+                <!-- 互评 -->
+                <TabPane :label="$t('studentWeb.homework.classComment')" name="classComment" v-if="homeworkInfo && homeworkInfo.allowComment && answerList && isEnd && students.length">
+                    <ClassmateCommentPages :homeWork="homeworkInfo" :students="students" @onPreview="onPreview" />
+                </TabPane>
+            </Tabs>
+        </vuescroll>
         
 		<div v-if="previewStatus" class="image-viewer">
 			<div style="width:fit-content;position:relative;margin:auto;">
@@ -680,51 +682,9 @@ export default {
 </script>
 
 <style lang="less" scoped>
-@import "~@/assets/student-web/component_styles/homework.less";
+@import "./Homework.less";
 </style>
 
 <style lang="less">
-.homework{
-    .ivu-tabs-nav {
-        float: left !important;
-        position: relative;
-        text-align: center;
-    }
-    .ivu-tabs-tab {
-        text-align: center !important;
-        font-size: 24px;
-        margin: 0px 10px;
-        width: auto;
-
-        &:hover {
-            text-align: center !important;
-            color: #24b880 !important;
-        }
-    }
-    .ivu-tabs-tab.ivu-tabs-tab-active.ivu-tabs-tab-focused {
-        color: #24b880 !important;
-        font-weight: bolder;
-        border-bottom: 5px solid #24b880 !important;
-        margin: 0px 10px;
-        width: auto;
-    }
-    .ivu-tabs-ink-bar {
-        height: 0px;
-    }
-    .ivu-tabs-tabpane {
-        margin-top: -16px;
-        overflow-x: hidden;
-        height: auto;
-    }
-
-    .upload-item {
-        position: relative;
-
-        .ivu-icon{
-            position: absolute;
-            top: 10px;
-            right: 15px;
-        }
-    }
-}
+@import "./HomeworkiView.less";
 </style>

+ 51 - 0
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/HomeworkiView.less

@@ -0,0 +1,51 @@
+@import '~@/assets/student-web/component_styles/color.less';
+
+.homework-content {
+
+    //評量成績報告的分頁組件
+    .ivu-tabs-nav {
+        float: left !important;
+        position: relative;
+        text-align: center;
+        z-index: 1;
+    }
+
+    .ivu-tabs-tab {
+        text-align: center !important;
+        font-size: 24px;
+        margin: 0px 10px;
+        width: auto;
+
+        &:hover {
+            text-align: center !important;
+            color: @primary  !important;
+        }
+    }
+
+    .ivu-tabs-tab.ivu-tabs-tab-active.ivu-tabs-tab-focused {
+        color: @primary  !important;
+        font-weight: bolder;
+        border-bottom: 5px solid @primary  !important;
+        margin: 0px 10px;
+        width: auto;
+    }
+
+    .ivu-tabs-ink-bar {
+        height: 0px;
+    }
+
+    .ivu-tabs-tabpane {
+        margin-top: -16px;
+        overflow-x: hidden;
+        height: auto;
+    }
+    
+    .upload-item {
+
+        .ivu-icon{
+            position: absolute;
+            top: 10px;
+            right: 15px;
+        }
+    }
+}

+ 16 - 13
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperViewBox/PaperView.less

@@ -1,4 +1,6 @@
-.lesson-test {
+.paper-content {
+    height: 100%;
+
     .paper-item {
         border: 1px solid #919191;
         font-weight: bolder;
@@ -53,18 +55,19 @@
         }
     }
 
-    .top-icon {
-        position: fixed;
-        right: 50px;
-        bottom: 20px;
-        width: 50px;
-        height: 50px;
-        line-height: 55px;
-        text-align: center;
-        background: #ccc;
-        border-radius: 5px;
-        cursor: pointer;
-    }
+}
+
+.top-icon {
+    position: fixed;
+    right: 50px;
+    bottom: 20px;
+    width: 50px;
+    height: 50px;
+    line-height: 55px;
+    text-align: center;
+    background: #ccc;
+    border-radius: 5px;
+    cursor: pointer;
 }
 
 .paper-tasks {

+ 9 - 8
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperViewBox/PaperView.vue

@@ -1,9 +1,9 @@
 <template>
-    <div class="lesson-test" id="paperView">
-        <!-- <PaperTest :papers="selectData" v-if="getisOpenLessonTestPopNow" />  -->
-            <Loading v-show="isLoad" bgColor="rgba(0, 0, 0, 0.3)"></Loading>
-        <!-- <div> -->
-                <EventBasicInfo :info="nowActive" :paper="paperData" />
+    <div class="event-content" id="paperView">
+        <Loading v-show="isLoad" bgColor="rgba(0, 0, 0, 0.3)"></Loading>
+        <vuescroll>
+            <EventBasicInfo :info="nowActive" :paper="paperData" />
+            <div class="paper-content">
                 <!--多學科試卷-->
                 <div v-if="paperData.length">
                     <div class="item-box" style="margin-bottom: 25px">
@@ -62,7 +62,8 @@
                         </div>
                     </TabPane> -->
                 </Tabs>
-        <!-- </div> -->
+            </div>
+        </vuescroll>
         <div class="top-icon" @click="gotoTop">
             <Icon type="ios-arrow-up" size="30" color="#249e35" />
         </div>
@@ -352,7 +353,7 @@
                 })
             },
             gotoTop() {
-                document.getElementsByClassName("lesson-test")[0].scrollIntoView()
+                document.getElementsByClassName("paper-content")[0].scrollIntoView()
             },
             /* =====未调用===== */
             dateFormat(timestamp) {
@@ -421,5 +422,5 @@
 </style>
 
 <style lang="less">
-@import "./PaperView-style.less";
+@import "./PaperViewiView.less";
 </style>

+ 1 - 1
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperViewBox/PaperView-style.less

@@ -1,4 +1,4 @@
-.lesson-test {
+.paper-content {
     /* height: 90vh; */
     padding-top: calc(1% + 15px);
 

+ 61 - 95
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/QuesNaire.vue

@@ -1,5 +1,5 @@
 <template>
-	<div class="quesnaire">
+	<div class="event-content">
 		<div v-if="WarmMessageisOpen" class="warmMessage">
 			<div class="messageCard animate__animated animate__fadeInDown">
 				<div v-if="showMessageNum == 1">
@@ -42,67 +42,69 @@
 			</Load>
 		</div> -->
 		<Loading v-show="isLoad" bgColor="rgba(0, 0, 0, 0.3)"></Loading>
-		<EventBasicInfo :info="nowActive" />
-		<div>
-			<!--問卷完成後,在時間結束前仍可修改答案再提交-->
-			<div style="margin-bottom: 100px;">
-				<div class="scoreboard" v-if="!alreadyAnswered && surveyInfo.progress === 'finish'">
-					<!-- 未作答 -->
-					<h4 style="padding: 25px;">
-						<svg-icon icon-class="handonHint" class="warm-icon" />
-						{{ $t('survey.studentWeb.noanswer') }}
-					</h4>
-				</div>
-				<!-- 描述 -->
-				<BillBoardandLightBox :activityData="surveyInfo" />
-				<!-- 内容 -->
-				<div class="title-rect-group" style="margin-bottom: 20px;">
-					<!-- <div class="title-rect" /> -->
-					<h2 class="title-rect-name">{{ $t('survey.studentWeb.content') }}</h2>
-				</div>
-				<!-- 问卷内容 -->
-				<template v-if="surveyInfo.items && surveyInfo.items.length">
-					<div v-for="(item, index) in surveyInfo.items" :key="index" class="survey-item">
-						<div style="display: flex; font-weight: bold;">
-							<span>{{ index + 1 }}. </span>
-							<span v-html="item.question" @click="showImg($event)"></span>({{ typeList[item.type] }})<span></span>
-						</div>
-						<!-- 非问答 -->
-						<div v-if="item.type !== 'subjective'">
-							<div class="unitTestBtn" v-for="(option, optionIndex) in item.option" :key="optionIndex">
-								<div class="unitTestbg" @click="onOptionClick(item, index, option.code)"
-									:style="{ backgroundColor: submitArr[index].includes(option.code) ? '#24b880' : 'transparent',
-												cursor: (alreadyAnswered || surveyInfo.progress === 'finish') ? 'not-allowed' : 'pointer'
-									}"
-								>
-									<span>
-										<Icon type="md-radio-button-off" v-show="!submitArr[index].includes(option.code)" />
-										<Icon type="md-radio-button-on" v-show="submitArr[index].includes(option.code)" />
-									</span>
-									<span v-html="option.value" style="margin-left: 10px;" @click="showImg($event)"></span>
+		<vuescroll>
+			<EventBasicInfo :info="nowActive" />
+			<div class="quesnaire-content">
+				<!--問卷完成後,在時間結束前仍可修改答案再提交-->
+				<div style="margin-bottom: 100px;">
+					<div class="scoreboard" v-if="!alreadyAnswered && surveyInfo.progress === 'finish'">
+						<!-- 未作答 -->
+						<h4 style="padding: 25px;">
+							<svg-icon icon-class="handonHint" class="warm-icon" />
+							{{ $t('survey.studentWeb.noanswer') }}
+						</h4>
+					</div>
+					<!-- 描述 -->
+					<BillBoardandLightBox :activityData="surveyInfo" />
+					<!-- 内容 -->
+					<div class="title-rect-group" style="margin-bottom: 20px;">
+						<!-- <div class="title-rect" /> -->
+						<h2 class="title-rect-name">{{ $t('survey.studentWeb.content') }}</h2>
+					</div>
+					<!-- 问卷内容 -->
+					<template v-if="surveyInfo.items && surveyInfo.items.length">
+						<div v-for="(item, index) in surveyInfo.items" :key="index" class="survey-item">
+							<div style="display: flex; font-weight: bold;">
+								<span>{{ index + 1 }}. </span>
+								<span v-html="item.question" @click="showImg($event)"></span>({{ typeList[item.type] }})<span></span>
+							</div>
+							<!-- 非问答 -->
+							<div v-if="item.type !== 'subjective'">
+								<div class="unitTestBtn" v-for="(option, optionIndex) in item.option" :key="optionIndex">
+									<div class="unitTestbg" @click="onOptionClick(item, index, option.code)"
+										:style="{ backgroundColor: submitArr[index].includes(option.code) ? '#24b880' : 'transparent',
+													cursor: (alreadyAnswered || surveyInfo.progress === 'finish') ? 'not-allowed' : 'pointer'
+										}"
+									>
+										<span>
+											<Icon type="md-radio-button-off" v-show="!submitArr[index].includes(option.code)" />
+											<Icon type="md-radio-button-on" v-show="submitArr[index].includes(option.code)" />
+										</span>
+										<span v-html="option.value" style="margin-left: 10px;" @click="showImg($event)"></span>
+									</div>
 								</div>
 							</div>
+							<!-- 问答 -->
+							<div v-if="item.type === 'subjective'">
+								<Input v-special-char v-model="submitArr[index][0]" type="textarea" :rows="8"
+										:placeholder="$t('studentWeb.exam.inputAnswers')"
+										:disabled="alreadyAnswered || surveyInfo.progress === 'finish'"
+								/>
+							</div>
+							<Divider v-if="index != surveyInfo.items.length - 1" />
 						</div>
-						<!-- 问答 -->
-						<div v-if="item.type === 'subjective'">
-							<Input v-special-char v-model="submitArr[index][0]" type="textarea" :rows="8"
-									:placeholder="$t('studentWeb.exam.inputAnswers')"
-									:disabled="alreadyAnswered || surveyInfo.progress === 'finish'"
-							/>
-						</div>
-						<Divider v-if="index != surveyInfo.items.length - 1" />
+					</template>
+					<div v-else class="no-data">
+						<img src="/img/no_data.6f25932b.svg" alt="">
+						<p>{{ $t('survey.questionaire.noItemData') }}</p>
 					</div>
-				</template>
-				<div v-else class="no-data">
-					<img src="/img/no_data.6f25932b.svg" alt="">
-					<p>{{ $t('survey.questionaire.noItemData') }}</p>
+					<button class="uploadBtn" @click="submitMessage()" v-if="!alreadyAnswered && surveyInfo.progress != 'finish'">
+						<svg-icon icon-class="quesnaire" class="uloadBtn-icon" />
+						<span>{{ $t('survey.studentWeb.submit') }}</span>
+					</button>
 				</div>
-				<button class="uploadBtn" @click="submitMessage()" v-if="!alreadyAnswered && surveyInfo.progress != 'finish'">
-					<svg-icon icon-class="quesnaire" class="uloadBtn-icon" />
-					<span>{{ $t('survey.studentWeb.submit') }}</span>
-				</button>
 			</div>
-		</div>
+		</vuescroll>
 		<!--图片放大显示-->
 		<Modal v-model="imgPreview.show" width="95">
             <img :src="imgPreview.img" style="width: 100%" />
@@ -488,45 +490,9 @@
 </script>
 
 <style lang="less" scoped>
-	@import "~@/assets/student-web/component_styles/quesnaire.less";
-</style>
-<style lang="less" scoped>
-.quesnaire {
-	.imgDolg {
-        width: 100vw;
-        height: 100vh;
-        position: fixed;
-        z-index: 9999;
-        background-color: rgba(140, 134, 134, 0.6);
-        top: 0;
-        left: 0;
-        display: flex;
-        align-items: center;
-        justify-content: center;
-    }
-
-    .imgDolg img {
-        width: 60%;
-        border: 1px solid #eee;
-        // height: 95%;
-    }
-
-    .imgDolg #imgDolgClose {
-        position: fixed;
-        top: 35px;
-        cursor: pointer;
-        right: 17%;
-        font-size: 50px;
-        color: white;
-    }
-}
+@import "./Quesnaire.less";
 </style>
 
 <style lang="less">
-.survey-item{
-	.ivu-input{
-		margin: 10px 0;
-		border-color: #9c9c9c;
-	}
-}
-</style>
+@import "./QuesnaireiView.less";
+</style>

+ 141 - 0
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/Quesnaire.less

@@ -0,0 +1,141 @@
+@import '~@/assets/student-web/component_styles/color.less';
+
+.quesnaire-content {
+    .unitTestBtn {
+        display: block !important;
+        margin: 0px;
+        width: 100% !important;
+
+        .unitTestbg {
+            cursor: pointer;
+            padding: 10px;
+            background-color: #fff;
+            border-radius: 4px;
+            border: 1px solid #8f8f8f;
+            margin-top: 10px;
+            display: flex;
+        }
+    }
+
+    .survey-item {
+        margin: 0 10px;
+
+        img {
+            width: 200px;
+        }
+    }
+
+    .uloadBtn-icon {
+        font-size: 18px;
+        position: relative;
+        top: 1px;
+        margin-right: 4px;
+    }
+
+    .commentArea {
+        width: 100%;
+        padding: 10px;
+        margin-top: 12px;
+        background: rgba(139, 139, 139, 0.1);
+        border: 1px solid @border;
+        border-radius: 6px;
+        color: #444444;
+
+        &:focus {
+            outline-color: #24b880;
+        }
+    }
+
+    .unitTestbtnWithImg {
+        display: inline-block !important;
+        margin: 10px;
+        width: 20% !important;
+        vertical-align: top;
+
+        .checkImg {
+            width: 100% !important;
+        }
+    }
+
+    .mustAns {
+        color: red
+    }
+
+    .undoNum,
+    .hintnoAns {
+        color: #fa6400;
+        font-weight: bolder;
+    }
+
+    .messageCardBtn {
+        width: 35%;
+        margin: 30px 5px 10px 5px;
+        padding: 5px;
+        border: none;
+        color: #6a6565;
+        font-weight: 500;
+        border-radius: 4px;
+        background: rgba(0, 0, 0, 0.1);
+        outline: none;
+        cursor: pointer;
+
+        &:hover {
+            background: rgba(0, 0, 0, 0.2);
+        }
+    }
+
+    .quesnairefinished-icon {
+        font-size: 60px;
+        position: relative;
+        left: 0px;
+        margin: 10px 0px;
+    }
+
+    .scoreboard {
+        width: 100%;
+        /*height: 638px;*/
+        background: rgb(240, 240, 240);
+        /*border: 1px solid rgba(0, 0, 0, 0.1);*/
+        border-radius: 8px;
+        padding: 15px;
+    }
+
+    .no-data {
+        text-align: center;
+
+        img {
+            max-width: 120px;
+            border: none;
+        }
+
+        font-size: 16px;
+    }
+
+    .imgDolg {
+        width: 100vw;
+        height: 100vh;
+        position: fixed;
+        z-index: 9999;
+        background-color: rgba(140, 134, 134, 0.6);
+        top: 0;
+        left: 0;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+    }
+
+    .imgDolg img {
+        width: 60%;
+        border: 1px solid #eee;
+        // height: 95%;
+    }
+
+    .imgDolg #imgDolgClose {
+        position: fixed;
+        top: 35px;
+        cursor: pointer;
+        right: 17%;
+        font-size: 50px;
+        color: white;
+    }
+}

+ 35 - 0
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/QuesnaireiView.less

@@ -0,0 +1,35 @@
+@import '~@/assets/student-web/component_styles/color.less';
+
+.quesnaire-content {
+    .unitTestBtn {
+
+        input[type="checkbox"],
+        input[type="radio"] {
+            visibility: hidden;
+            margin-left: -10px;
+
+            &:checked {
+                ~.unitTestbg {
+                    background-color: #24b880 !important;
+                    border: none;
+                    color: #fff;
+                    font-weight: bolder;
+                }
+            }
+        }
+    }
+
+    .scoreboard {
+
+        .ivu-card {
+            margin-bottom: 20px;
+        }
+    }
+
+    .survey-item {
+        .ivu-input {
+            margin: 10px 0;
+            border-color: #9c9c9c;
+        }
+    }
+}

+ 89 - 139
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/Vote.vue

@@ -1,5 +1,5 @@
 <template>
-    <div class="vote">
+    <div class="event-content">
         <div v-if="WarmMessageisOpen" class="warmMessage ">
             <div class="messageCard animate__animated animate__fadeInDown ">
                 <h2>{{ $t("studentWeb.vote.voteSuccess") }}</h2>
@@ -7,97 +7,99 @@
                 <p>{{ $t("studentWeb.vote.voteDes") }}</p>
             </div>
         </div>
-        <EventBasicInfo :info="nowActive" :times="voteTimes" />
-        <div>
-            <!-- <div> -->
-                <!--超时-->
-                <div v-show="!isVote && !isVoteOK">
-                    <br />
-                    <div class="dec animate__animated animate__bounceInLeft">
-                        <svg-icon icon-class="handonHint" class="warm-icon" />
-                        <span class="warm-hint">{{ $t("studentWeb.vote.timeoutHint") }}</span>
+        <Loading v-show="isLoad" bgColor="rgba(0, 0, 0, 0.3)"></Loading>
+        <vuescroll>
+            <EventBasicInfo :info="nowActive" :times="voteTimes" />
+            <div class="vote-content">
+                <!-- <div> -->
+                    <!--超时-->
+                    <div v-show="!isVote && !isVoteOK">
+                        <br />
+                        <div class="dec animate__animated animate__bounceInLeft">
+                            <svg-icon icon-class="handonHint" class="warm-icon" />
+                            <span class="warm-hint">{{ $t("studentWeb.vote.timeoutHint") }}</span>
+                        </div>
+                    </div>
+                    <!-- <div class="load-box">
+                        <Load :active.sync="isLoad"
+                            background-color="#000">
+                            <template slot="default">
+                                <svg-icon icon-class="loader" class="loader-icon" />
+                            </template>
+                        </Load>
+                    </div> -->
+                    <BillBoardandLightBox :activityData="voteInfo" :voteRes="voteResData" />
+                    <!-- 投票结果 -->
+                    <div class="voteResults" v-if="showResult">
+                        <div class="vote-title">
+                            <div class="title-rect-group">
+                                <h2 class="title-rect-name">{{ $t("studentWeb.vote.voteResult") }}</h2>
+                            </div>
+                        </div>
+                        <div align="center">
+                            <VoteResultChart :voteData="voteData" :voteList="voteList" />
+                        </div>
                     </div>
-                </div>
-                <!-- <div class="load-box">
-                    <Load :active.sync="isLoad"
-                        background-color="#000">
-                        <template slot="default">
-                            <svg-icon icon-class="loader" class="loader-icon" />
-                        </template>
-                    </Load>
-                </div> -->
-                <Loading v-show="isLoad" bgColor="rgba(0, 0, 0, 0.3)"></Loading>
-                <BillBoardandLightBox :activityData="voteInfo" :voteRes="voteResData" />
-                <!-- 投票结果 -->
-                <div class="voteResults" v-if="showResult">
                     <div class="vote-title">
                         <div class="title-rect-group">
-                            <h2 class="title-rect-name">{{ $t("studentWeb.vote.voteResult") }}</h2>
+                            <h2 class="title-rect-name">{{ $t("studentWeb.vote.bollotbox") }}</h2>
+                            <p v-if="!isVoteOK && (voteInfo.times != 'once' || voteInfo.repeat)" style="margin-left:15px;margin-top:2px">
+                                {{ $t("studentWeb.vote.surplusTickets")}}
+                                <span style="font-size:16px">{{ voteCount }}</span>
+                                <span> {{ $t("studentWeb.vote.tickets")}} </span>
+                            </p>
                         </div>
                     </div>
-                    <div align="center">
-                        <VoteResultChart :voteData="voteData" :voteList="voteList" />
-                    </div>
-                </div>
-                <div class="vote-title">
-                    <div class="title-rect-group">
-                        <h2 class="title-rect-name">{{ $t("studentWeb.vote.bollotbox") }}</h2>
-                        <p v-if="!isVoteOK && (voteInfo.times != 'once' || voteInfo.repeat)" style="margin-left:15px;margin-top:2px">
-                            {{ $t("studentWeb.vote.surplusTickets")}}
-                            <span style="font-size:16px">{{ voteCount }}</span>
-                            <span> {{ $t("studentWeb.vote.tickets")}} </span>
-                        </p>
-                    </div>
-                </div>
-                <div class="vote-option">
-                    <!-- 只投一次 -->
-                    <CheckboxGroup v-model="voteChecked" v-if="voteInfo.times == 'once' && !voteInfo.repeat" class="option-group" @on-change="controlNum">
-                        <Checkbox border
-                            :label="item.code"
-                            v-for="(item, index) in voteInfo.options"
-                            :key="index"
-                            class="option-wrapper"
-                            :disabled="!isVote"
-                        >
-                            <span>
-                                <Icon type="md-radio-button-off" v-show="!voteChecked.includes(item.code)" />
-                                <Icon type="md-radio-button-on" v-show="voteChecked.includes(item.code)" />
-                            </span>
-                            <span v-html="item.value" @click="showImg($event)"></span>
-                        </Checkbox>
-                    </CheckboxGroup>
-                    <!-- 重复投票 -->
-                    <div v-else>
-                        <div v-for="(item, index) in voteInfo.options"
-                            :key="index"
-                            :class="['option-repeat', {'action-rep': item.count}]"
-                        >
-                            <InputNumber v-model="item.count"
-                                        controls-outside
-                                        :min="0"
-                                        :max="!voteInfo.repeat ? 1 : Infinity"
-                                        :formatter="value => `${value}` +$t('studentWeb.vote.tickets')"
-                                        :disabled="!isVote || isVoteOK"
-                            ></InputNumber>
-                            <span style="margin-right: 5px;">
-                                <Icon type="md-radio-button-off" v-show="!item.count" />
-                                <Icon type="md-radio-button-on" v-show="item.count" />
-                            </span>
-                            <span v-html="item.value" @click="showImg($event)"></span>
+                    <div class="vote-option">
+                        <!-- 只投一次 -->
+                        <CheckboxGroup v-model="voteChecked" v-if="voteInfo.times == 'once' && !voteInfo.repeat" class="option-group" @on-change="controlNum">
+                            <Checkbox border
+                                :label="item.code"
+                                v-for="(item, index) in voteInfo.options"
+                                :key="index"
+                                class="option-wrapper"
+                                :disabled="!isVote"
+                            >
+                                <span>
+                                    <Icon type="md-radio-button-off" v-show="!voteChecked.includes(item.code)" />
+                                    <Icon type="md-radio-button-on" v-show="voteChecked.includes(item.code)" />
+                                </span>
+                                <span v-html="item.value" @click="showImg($event)"></span>
+                            </Checkbox>
+                        </CheckboxGroup>
+                        <!-- 重复投票 -->
+                        <div v-else>
+                            <div v-for="(item, index) in voteInfo.options"
+                                :key="index"
+                                :class="['option-repeat', {'action-rep': item.count}]"
+                            >
+                                <InputNumber v-model="item.count"
+                                            controls-outside
+                                            :min="0"
+                                            :max="!voteInfo.repeat ? 1 : Infinity"
+                                            :formatter="value => `${value}` +$t('studentWeb.vote.tickets')"
+                                            :disabled="!isVote || isVoteOK"
+                                ></InputNumber>
+                                <span style="margin-right: 5px;">
+                                    <Icon type="md-radio-button-off" v-show="!item.count" />
+                                    <Icon type="md-radio-button-on" v-show="item.count" />
+                                </span>
+                                <span v-html="item.value" @click="showImg($event)"></span>
+                            </div>
                         </div>
                     </div>
-                </div>
-                <div v-if="!showResult">
-                    <Button :disabled="isVoteOK" size="large" type="success" @click="submitMessage()">
-                        <svg-icon icon-class="vote" class="uploadBtn-icon" />
-                        <span style="margin-left:5px">{{ isVoteOK ? $t("studentWeb.vote.submitOKVote") : $t("studentWeb.vote.submitBVote") }}</span>
-                    </Button>
-                    <span class="clickbutnoChoosehint"
-                        v-if="clickbutnoChoose == true && voteChecked == ''">{{ $t("studentWeb.vote.note") }}</span>
-                    <span v-if="isOverCount && !isVoteOK" style="margin-top:5px;margin-left:15px;color:red">{{$t("studentWeb.vote.warning2")}}</span>
-                </div>
-            <!-- </div> -->
-        </div>
+                    <div v-if="!showResult">
+                        <Button :disabled="isVoteOK" size="large" type="success" @click="submitMessage()">
+                            <svg-icon icon-class="vote" class="uploadBtn-icon" />
+                            <span style="margin-left:5px">{{ isVoteOK ? $t("studentWeb.vote.submitOKVote") : $t("studentWeb.vote.submitBVote") }}</span>
+                        </Button>
+                        <span class="clickbutnoChoosehint"
+                            v-if="clickbutnoChoose == true && voteChecked == ''">{{ $t("studentWeb.vote.note") }}</span>
+                        <span v-if="isOverCount && !isVoteOK" style="margin-top:5px;margin-left:15px;color:red">{{$t("studentWeb.vote.warning2")}}</span>
+                    </div>
+                <!-- </div> -->
+            </div>
+        </vuescroll>
         <!--图片放大显示-->
         <Modal v-model="imgPreview.show" width="95">
             <img :src="imgPreview.img" style="width: 100%" />
@@ -586,61 +588,9 @@
 </script>
 
 <style lang="less" scoped>
-    @import "~@/assets/student-web/component_styles/vote.less";
-</style>
-<style lang="less" scoped>
-.vote {
-    .imgDolg {
-        width: 100vw;
-        height: 100vh;
-        position: fixed;
-        z-index: 9999;
-        background-color: rgba(140, 134, 134, 0.6);
-        top: 0;
-        left: 0;
-        display: flex;
-        align-items: center;
-        justify-content: center;
-    }
-
-    .imgDolg img {
-        width: 60%;
-        border: 1px solid #eee;
-        // height: 95%;
-    }
-
-    .imgDolg #imgDolgClose {
-        position: fixed;
-        top: 35px;
-        cursor: pointer;
-        right: 17%;
-        font-size: 50px;
-        color: white;
-    }
-}
+@import "./vote.less";
 </style>
 
 <style lang="less">
-.vote {
-    .ivu-checkbox-wrapper-checked.ivu-checkbox-border{
-        background-color: #19BE6B;
-        color: #fff;
-    }
-    .ivu-checkbox{
-        display: none;
-    }
-
-    .ivu-checkbox-border{
-        height: auto;
-    }
-
-    label.option-wrapper img,
-    .option-repeat img{
-        width: 200px !important;
-    }
-
-    .ivu-input-number-input[disabled]{
-        color: #666;
-    }
-}
+@import "./voteiView.less";
 </style>

+ 179 - 0
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/vote.less

@@ -0,0 +1,179 @@
+@import '~@/assets/student-web/component_styles/color.less';
+
+.vote-content {
+    height: calc(100% - 80px);
+
+    //投票區按鈕
+    .vote-option {
+        margin-top: 15px;
+        margin-bottom: 10px;
+
+        .option-group {
+            display: flex;
+            flex-direction: column;
+
+            .option-wrapper {
+                margin-bottom: 15px;
+                display: flex;
+                align-items: center;
+                // font-weight: 600;
+                border: 1px solid #ccc;
+                padding: 20px 10px;
+
+                .ivu-checkbox {
+                    margin-right: 5px;
+                }
+            }
+        }
+    }
+
+    .option-repeat {
+        display: flex;
+        align-items: center;
+        margin-bottom: 15px;
+        border: 1px solid #ccc;
+        padding: 15px 10px;
+        border-radius: 4px;
+    }
+
+    .action-rep {
+        background-color: #19BE6B;
+        color: #fff;
+    }
+
+    .checkAnswer {
+        display: block;
+        margin-top: 20px;
+        margin-left: 0px;
+
+        .testBtn {
+            margin: 20px 0px;
+            position: relative;
+            z-index: 2;
+            font-weight: bolder;
+            padding-left: 20px;
+            cursor: pointer;
+        }
+
+
+        .testbg {
+            cursor: pointer;
+            background-color: #fff;
+            position: relative;
+            height: auto;
+            top: -31px;
+            padding: 10px;
+            z-index: 1;
+            display: flex;
+            border-radius: 4px;
+            border: 1px solid #c5c5c5;
+        }
+    }
+
+    //送出訊息動畫
+    .slide-fade-enter-active {
+        transition: all 0.3s ease;
+    }
+
+    .slide-fade-leave-active {
+        transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
+    }
+
+    .slide-fade-enter,
+    .slide-fade-leave-to
+
+    /* .slide-fade-leave-active for below version 2.1.8 */
+        {
+        transform: translateY(-5%);
+        opacity: 0;
+    }
+
+    .votefinished-icon {
+        font-size: 80px;
+        position: relative;
+        left: -3px;
+        margin-bottom: 10px;
+    }
+
+    //活動結果
+    .voteResultsItem {
+        padding: 10px 20px;
+        padding-left: 80px;
+        z-index: 0 !important;
+        position: relative;
+    }
+
+    .voteResultsIcon {
+        font-size: 20px;
+        color: @primary;
+        position: absolute;
+        top: 0;
+        right: 0;
+        bottom: 0;
+        left: 2%;
+        margin: auto 0;
+    }
+
+    .voteResultSelect {
+        background-color: rgba(229, 229, 229, 0.56);
+        border-radius: 4px;
+    }
+
+    .voteResultsMainRow {
+        background-color: rgba(229, 229, 229, 0.56);
+        padding: 20px;
+        border-radius: 4px;
+    }
+
+    .voteResultsMainKeyWord {
+        color: #24b880;
+        font-size: 24px;
+        position: relative;
+        top: 2px;
+    }
+
+    .vote-chart-card {
+        width: 50%;
+
+        @media screen and (max-width: 1200px) {
+            width: 70%;
+        }
+
+        @media screen and (max-width: 767px) {
+            width: 100%;
+        }
+    }
+
+    .warnText {
+        color: red;
+        margin-left: 10px;
+    }
+
+    .imgDolg {
+        width: 100vw;
+        height: 100vh;
+        position: fixed;
+        z-index: 9999;
+        background-color: rgba(140, 134, 134, 0.6);
+        top: 0;
+        left: 0;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+
+        img {
+            width: 60%;
+            border: 1px solid #eee;
+            // height: 95%;
+        }
+
+        #imgDolgClose {
+            position: fixed;
+            top: 35px;
+            cursor: pointer;
+            right: 17%;
+            font-size: 50px;
+            color: white;
+        }
+    }
+}

+ 62 - 0
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/voteiView.less

@@ -0,0 +1,62 @@
+@import '~@/assets/student-web/component_styles/color.less';
+
+.vote-content {
+
+    .option-repeat {
+
+        .ivu-checkbox {
+            display: none;
+        }
+
+        .ivu-input-number {
+            margin-right: 15px;
+            width: 120px;
+        }
+    }
+
+    .checkAnswer {
+
+        .testBtn {
+
+            input[type="checkbox"] {
+                visibility: hidden;
+                margin-left: -10px;
+
+                &:checked {
+                    ~.testbg {
+                        background-color: @primary  !important;
+                        border: none;
+
+                        span {
+                            color: #fff;
+                            font-weight: bolder;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /* iview组件 */
+    .ivu-checkbox-wrapper-checked.ivu-checkbox-border {
+        background-color: #19BE6B;
+        color: #fff;
+    }
+
+    .ivu-checkbox {
+        display: none;
+    }
+
+    .ivu-checkbox-border {
+        height: auto;
+    }
+
+    label.option-wrapper img,
+    .option-repeat img {
+        width: 200px !important;
+    }
+    
+    .ivu-input-number-input[disabled]{
+        color: #666;
+    }
+}

+ 165 - 133
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventList.less

@@ -1,168 +1,200 @@
-.list-new {
-    display: flex;
-    border-bottom: 1px solid rgba(0, 0, 0, .1);
-    padding: 15px 10px 15px 25px;
-
-    &:hover {
-        background: linear-gradient(-270deg, #fafafa, #d4ede1);
-        color: #03966a;
-        cursor: pointer;
-    }
-
-    &-icon {
-        width: 10%;
-        margin-right: 30px;
+.event-list {
+    .list-new {
         display: flex;
-        justify-content: center;
-        flex-direction: column;
+        border-bottom: 1px solid rgba(0, 0, 0, .1);
+        padding: 15px 10px 15px 25px;
 
-        .svg-icon {
-            width: 40px;
-            height: 40px;
+        &:hover {
+            background: linear-gradient(-270deg, #fafafa, #d4ede1);
+            color: #03966a;
+            cursor: pointer;
         }
-    }
 
-    &-test {
-        width: 60%;
-        font-weight: bolder;
-        font-size: 14px;
-        line-height: 22px;
-        margin-right: 20px;
-        clear: both;
-
-        .list-item-typeMark {
-            text-align: center;
-            background-color: #dfdfdf;
-            border-radius: 10px;
-            padding: 1px 10px;
-            margin: 0 8px 0 -10px;
+        &-icon {
+            width: 10%;
+            margin-right: 30px;
+            display: flex;
+            justify-content: center;
+            flex-direction: column;
+
+            .svg-icon {
+                width: 40px;
+                height: 40px;
+            }
         }
 
-        .list-item-time {
-            color: #8f8787;
-            font-size: 12px;
+        &-test {
+            width: 60%;
+            font-weight: bolder;
+            font-size: 14px;
+            line-height: 22px;
+            margin-right: 20px;
+            clear: both;
+
+            .list-item-typeMark {
+                text-align: center;
+                background-color: #dfdfdf;
+                border-radius: 10px;
+                padding: 1px 10px;
+                margin: 0 8px 0 -10px;
+            }
+
+            .list-item-time {
+                color: #8f8787;
+                font-size: 12px;
+            }
+
+            /* .list-item-title {
+                font-size: 16px;
+                margin: 5px 0;
+            } */
+
+            .isScore {
+                float: right;
+            }
         }
 
-        /* .list-item-title {
-            font-size: 16px;
-            margin: 5px 0;
-        } */
-
-        .isScore {
-            float: right;
+        &-type {
+            width: 20%;
+            display: flex;
+            justify-content: center;
+            flex-direction: column;
+
+            .list-new-unDone {
+                font-size: 10px;
+                font-weight: bolder;
+                // color: #fff;
+                padding: 5px;
+                border-radius: 4px;
+                text-align: center;
+                border: 1px solid;
+
+
+            }
+
+            .isAllowRetry {
+                color: #fff;
+                background-color: #64ae16;
+                border: none;
+            }
+
+            .isWrongPra {
+                margin-top: 10px;
+            }
         }
-    }
 
-    &-type {
-        width: 20%;
-        display: flex;
-        justify-content: center;
-        flex-direction: column;
+        .text-long {
+            max-width: 150px;
+            height: 16px;
+            line-height: 16px;
+            display: inline-block;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            white-space: nowrap;
+        }
 
-        .list-new-unDone {
-            font-size: 10px;
+        .paper-item-school {
             font-weight: bolder;
-            // color: #fff;
-            padding: 5px;
-            border-radius: 4px;
-            text-align: center;
-            border: 1px solid;
-
+            height: 20px;
+            line-height: 18px;
+            // padding: 5px 2px;
+            // margin-top: 10px;
+            // margin-right: 20px;
+            margin-bottom: 5px;
+            cursor: pointer;
+            display: inline-flex;
+            font-size: 12px;
 
+            .other-owner {
+                background-color: #ababab;
+                color: #fff;
+                border-radius: 5px 0 0 5px;
+            }
+
+            .paper-owner {
+                background-color: #ababab;
+                color: #fff;
+                border-radius: 5px 0 0 5px;
+            }
+
+            .paper-extType {
+                border: 1px solid #ababab;
+                border-radius: 0 5px 5px 0;
+                border-left: none;
+            }
+
+            .paper-source {
+                border: 1px solid #ababab;
+                // border-radius: 0 5px 5px 0;
+            }
+
+            &>span {
+                padding: 0 5px;
+                white-space: pre;
+            }
+
+            &>p {
+                margin-left: 10px;
+                font-size: 14px;
+            }
         }
+    }
 
-        .isAllowRetry {
+    // 未开展标识
+    .dev-top {
+        .develop {
+            position: absolute;
+            top: 1px;
+            right: -13px;
+            font-size: xx-small;
             color: #fff;
-            background-color: #64ae16;
-            border: none;
+            padding: 2px 5px;
+            z-index: 99;
+            transform: scale(0.7) rotate(45deg);
         }
 
-        .isWrongPra {
-            margin-top: 10px;
+        &::after {
+            position: absolute;
+            content: " ";
+            right: 0px;
+            top: -4px;
+            z-index: 0;
+            width: 33px;
+            height: 20px;
+            background-color: #64AE16;
+            transform: skewY(45deg);
         }
     }
 
-    .text-long {
-        max-width: 150px;
-        height: 16px;
-        line-height: 16px;
-        display: inline-block;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        white-space: nowrap;
+    .tag-pointer {
+        background-color: #6b6ba9;
+        color: #fff;
     }
 
-    .paper-item-school {
-        font-weight: bolder;
-        height: 20px;
-        line-height: 18px;
-        // padding: 5px 2px;
-        // margin-top: 10px;
-        // margin-right: 20px;
-        margin-bottom: 5px;
-        cursor: pointer;
-        display: inline-flex;
-        font-size: 12px;
-
-        .other-owner {
-            background-color: #ababab;
-            color: #fff;
-            border-radius: 5px 0 0 5px;
-        }
-
-        .paper-owner {
-            background-color: #ababab;
-            color: #fff;
-            border-radius: 5px 0 0 5px;
-        }
-
-        .paper-extType {
-            border: 1px solid #ababab;
-            border-radius: 0 5px 5px 0;
-            border-left: none;
-        }
+    .event-selector-block {
+        padding: 17px 25px;
 
-        .paper-source {
-            border: 1px solid #ababab;
-            // border-radius: 0 5px 5px 0;
+        .list-title {
+            font-size: 18px;
+            text-decoration: none;
+            color: #515a6e;
         }
-
-        &>span {
-            padding: 0 5px;
-            white-space: pre;
-        }
-
-        &>p {
-            margin-left: 10px;
+        
+        .tag-teacher {
             font-size: 14px;
+            padding: 1px 7px;
+            border-radius: 5px;
         }
     }
-}
 
-// 未开展标识
-.dev-top {
-    .develop {
-        position: absolute;
-        top: 1px;
-        right: -13px;
-        font-size: xx-small;
-        color: #fff;
-        padding: 2px 5px;
-        z-index: 99;
-        transform: scale(0.7) rotate(45deg);
+    .list-block-1 {
+        height: calc(100% - 108px);
     }
 
-    &::after {
-        position: absolute;
-        content: " ";
-        right: 0px;
-        top: -4px;
-        z-index: 0;
-        width: 33px;
-        height: 20px;
-        background-color: #64AE16;
-        transform: skewY(45deg);
+    .list-block-2 {
+        height: calc(100% - 210px);
     }
+
 }
 
 @media screen and (max-width: 1280px) {

+ 124 - 40
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventList.vue

@@ -1,7 +1,7 @@
 <template>
-    <div>
+    <div class="layout-content-wrap event-list">
         <Loading v-show="isLoad" bgColor="rgba(0, 0, 0, 0.3)"></Loading>
-        <div class="list" v-show="getSidebarisOpen">
+        <div class="layout-left-wrap" v-show="getSidebarisOpen">
             <!--活動搜尋與篩選區域-->
             <div class="event-selector-block">
                 <div class="search">
@@ -18,13 +18,20 @@
                 <div>
                     <Dropdown>
                         <a href="javascript:void(0)" class="list-title">
-                            <span>{{ selectedEventStatusNow }}</span>
+                            <span>{{ selectedEventStatusNow.status }}</span>
                             <Icon type="ios-arrow-down"></Icon>
                         </a>
                         <DropdownMenu slot="list">
-                            <div @click="sentEventStatus(item)" v-for="(item, index) in $t('studentWeb.state')" :key="index">
-                                <DropdownItem>{{ item.status }}</DropdownItem>
-                            </div>
+                            <template v-if="showType[0] === 'Exam'">
+                                <div @click="sentEventStatus(item)" v-for="(item, index) in $t('studentWeb.state1')" :key="index">
+                                    <DropdownItem>{{ item.status }}</DropdownItem>
+                                </div>
+                            </template>
+                            <template v-else>
+                                <div @click="sentEventStatus(item)" v-for="(item, index) in $t('studentWeb.state2')" :key="index">
+                                    <DropdownItem>{{ item.status }}</DropdownItem>
+                                </div>
+                            </template>
                         </DropdownMenu>
                     </Dropdown>
                 </div>
@@ -34,12 +41,12 @@
                                 class="icon-selector-group"
                                 @on-change="predealMockdatafirstItem()"
                     >
-                        <div class="icon-btn"
+                        <!-- <div class="icon-btn"
                             @click="selectAllType()"
                             :title="$t('studentWeb.type.all')"
                             :class="{'icon-btn-selected': eventTypeCheckers == ''}">
                             <svg-icon icon-class="alltext" class="innerIcon Icon-0" />
-                        </div>
+                        </div> -->
                         <template>
                             <Radio :label="iconBtn.eventType"
                                 v-for="(iconBtn, index) in showTypeNametoIcon"
@@ -62,22 +69,30 @@
                     </RadioGroup>
                 </div>
                 <!---按鈕搜尋區(多選)--->
-                <div style="margin-top: 10px;">
+                <div style="margin-top: 15px;">
                     <span>{{ $t("studentWeb.choiceTime") }}:</span>
                     <DatePicker type="date" :value="choDate" :options="options" @on-change="dateChange" :placeholder="$t('studentWeb.missionListCardPlace')" />
                 </div>
+                <div style="margin-top: 15px;" v-if="showType.length === 2">
+                    <span>{{ $t('studentWeb.vote.choiceTeacher') }}:</span>
+                    <span class="tag-style tag-teacher" :class="{'tag-pointer': !nowTea}" style="cursor: pointer;" @click="changeTea(0)">{{ $t('studentWeb.type.all') }}</span>
+                    <span v-for="(tea, tIndex) in teachers" :key="tIndex" @click="changeTea(tIndex + 1, tea)"
+                        class="tag-style tag-teacher" :class="{'tag-pointer': nowTea === (tIndex + 1)}" style="cursor: pointer;"
+                    >
+                        {{ tea.name }}
+                    </span>
+                </div>
             </div>
             <!--活動清單分頁-->
-            <div class="list-block"
-                :style="{ height: !hideIconbtn ? '84vh' : '90vh' }">
+            <div :class="['list-block', showType.length === 1 ? 'list-block-1' : 'list-block-2']">
                 <!-- 空 -->
-                <div v-show="isListNoItem" class="emptycondition">
+                <div v-if="isListNoItem" class="emptycondition">
                     <svg-icon icon-class="empty-white-box" class="empty-Icon" />
                     <br />
                     {{ $t("studentWeb.empty") }}
                 </div>
-                <vuescroll>
-                    <div v-if="!isListNoItem" style="margin-bottom: 100px">
+                <vuescroll v-else>
+                    <div style="margin-bottom: 100px">
                         <div :id="`event${item.id}`"
                             class="list-new"
                             @click="sentSelectedEventTitle(item)"
@@ -145,7 +160,7 @@
                                 <!-- <p class="list-item-time isScore" v-show="timeStatus(item) == 'finish'">
                                     得分率:20%
                                 </p> -->
-                                <p style="font-size:12px; margin-top: 5px; word-break: keep-all;">
+                                <!-- <p style="font-size:12px; margin-top: 5px; word-break: keep-all;">
                                     <span v-if="item.ext">
                                         <span v-if="item.ext.subjects">
                                             <span v-for="(item, index) in item.ext.subjects" :key="index"
@@ -165,7 +180,7 @@
                                     <span class="tag-style tag-teacher text-long" v-if="item.teacherName" :title="item.teacherName">
                                         {{ item.teacherName }}
                                     </span>
-                                </p>
+                                </p> -->
                                 <p class="list-item-time">
                                     {{ dateFormat(item.startTime) }} ~ {{ dateFormat(item.endTime) }}
                                 </p>
@@ -252,7 +267,7 @@
                                 <div class="paper-item-school">
                                     <span class="paper-owner" v-if="item.owner === 'school'" style="background-color: #88a1d8;">{{ $t('studentWeb.public.school') }}</span>
                                     <span class="paper-owner" v-else>{{ $t('studentWeb.public.private') }}</span>
-                                    <span class="paper-source">
+                                    <span :class="item.mustSubmit ? 'paper-source' : 'paper-extType'">
                                         {{ $t('studentWeb.home.homework') }}
                                     </span>
                                     <span class="paper-extType" v-if="item.mustSubmit" style="color: #dc8f57;"
@@ -317,23 +332,23 @@
                 <div class="list-end"></div>
             </div>
         </div>
-        <div class="eventContentArea-view" :class="{'no-bar': !getSidebarisOpen}">
+        <div class="layout-right-wrap" :class="{'no-bar-content': getSidebarisOpen}">
             <!--<VoteHint v-if="this.$store.getters.getisVoteResulthover==true"/>-->
             <template v-if="nowActivity">
 
                 <!--<div v-if="getItemTitle.type=='preview'">
                     <PreviewMission />
                 </div>-->
-                <div v-if="nowActivity.type === 'Homework'">
+                <div v-if="nowActivity.type === 'Homework'" class="event-content">
                     <Homework />
                 </div>
-                <div v-if="nowActivity.type === 'Exam'">
+                <div v-if="nowActivity.type === 'Exam'" class="event-content">
                     <PaperView />
                 </div>
-                <div v-if="nowActivity.type === 'Vote'">
+                <div v-if="nowActivity.type === 'Vote'" class="event-content">
                     <Vote />
                 </div>
-                <div v-if="nowActivity.type === 'Survey'">
+                <div v-if="nowActivity.type === 'Survey'" class="event-content">
                     <QuesNaire />
                 </div>
             </template>
@@ -382,6 +397,7 @@ import QuesNaire from "./EventContentTypeTemplate/QuesNaire";
             this.showTypeNametoIcon = this.typeNametoIcon.filter(item => {
                 return this.showType.includes(item.eventType)
             })
+            this.eventTypeCheckers = this.showType.length === 1 ? '' : 'Vote'
             if(this.getChoseDate) {
                 this.dateChange(this.getChoseDate)
             } else {
@@ -429,7 +445,10 @@ import QuesNaire from "./EventContentTypeTemplate/QuesNaire";
                 eventList: [], //活动数据
                 eventShow: [], //展示的活动数据
                 eventPageType: ["Learn", "Exam", "Homework", "Vote", "Survey"], //本頁出現的類型
-                selectedEventStatusNow: this.$t('studentWeb.event.allStatus'), //下拉框活动状态
+                selectedEventStatusNow: {
+                    type: "all",
+                    status: this.$t('studentWeb.event.allStatus')
+                }, //下拉框活动状态
                 openSearch: false, //打開搜尋器
                 search: "",
                 hideIconbtn: false,
@@ -451,6 +470,8 @@ import QuesNaire from "./EventContentTypeTemplate/QuesNaire";
                 countDown: null,
                 nowActivity: undefined, //现在选择的活动
                 isLoad: false,
+                teachers: [],
+                nowTea: 0,
             };
         },
         // components: { PreviewProgressPie },
@@ -504,8 +525,12 @@ import QuesNaire from "./EventContentTypeTemplate/QuesNaire";
                 "getFinishedItem",
                 "getFinishedItemTime",
                 "getChoseDate",
-                "getSidebarisOpen"
-            ])
+                "getSidebarisOpen",
+                "getNowCourse",
+            ]),
+            courseNow() {
+                return this.getNowCourse || JSON.parse(decodeURIComponent(localStorage.course, "utf-8"))
+            },
         },
         methods: {
             //获取活动信息数据
@@ -577,12 +602,41 @@ import QuesNaire from "./EventContentTypeTemplate/QuesNaire";
                         }
                         // this.eventList = [...data]
                         this.eventList = data.filter(item => {
-                            return this.showType.includes(item.type)
+                            /**
+                             * 1. 筛选类型(评测、作业)
+                             * 2. 匹配名单
+                             * 3. 科目、课程有一个匹配即可
+                             */
+                            // 目前评测、作业都只传了一个值
+                            if(this.showType.length === 1) {
+                            // if(this.showType[0] === 'Exam') {
+                                return this.showType.includes(item.type) && item.classIds.includes(this.courseNow.list) &&
+                                    (item.subjects.includes(this.courseNow.subject.id) || item.subjects.includes(this.courseNow.id))
+                            } else {
+                                return this.showType.includes(item.type)
+                            }
                         })
                         this.eventList = this.eventList.sort(function (a, b) {
                             return b.startTime - a.startTime //时间正序
                         });
-                        this.eventShow = [...this.eventList]
+                        if(this.showType.length === 2) {
+                            this.eventList.forEach(item => {
+                                if(!this.teachers.find(tea => {
+                                    return tea.id === item.creatorId
+                                })) {
+                                    this.teachers.push({
+                                        id: item.creatorId,
+                                        name: item.teacherName
+                                    })
+                                }
+                                if(item.type === 'Vote') {
+                                    this.eventShow.push(item)
+                                }
+                            })
+                        } else {
+                            this.eventShow = [...this.eventList]
+                        }
+                        
                         if(this.eventShow.length) {
                             let twoDay = 24 * 3600 * 1000 * 2
                             this.countDown = setInterval(() => {
@@ -696,7 +750,7 @@ import QuesNaire from "./EventContentTypeTemplate/QuesNaire";
                 if (status == "reMake" || status == "reExam") {
                     this.eventTypeCheckers = "";
                 }
-                this.selectedEventStatusNow = status.status;
+                this.selectedEventStatusNow = status;
                 this.predealMockdatafirstItem();
             },
             // 状态 + 类型筛选
@@ -707,29 +761,33 @@ import QuesNaire from "./EventContentTypeTemplate/QuesNaire";
                 for (let i = 0; i < this.eventList.length; i++) {
                     if (this.eventPageType.includes(this.eventList[i].type)) {
                         // 沒有篩選類型+沒有篩選狀態的情況
-                        if (this.eventTypeCheckers == "" && this.selectedEventStatusNow == "所有活动状态") {
+                        if (this.eventTypeCheckers == "" && this.selectedEventStatusNow.type == "all") {
                             currentfilterArray.push(this.eventList[i]);
                         }
                         // 沒篩選類型+有篩選狀態的情況
                         else if (this.eventTypeCheckers == "" &&
-                            this.dropDownShowCondition(this.selectedEventStatusNow, this.eventList[i])) {
+                            this.dropDownShowCondition(this.selectedEventStatusNow.type, this.eventList[i])) {
                             currentfilterArray.push(this.eventList[i]);
                         }
                         // 有篩選類型+有篩選狀態的情況
                         else if (
                             this.eventTypeCheckers !== "" &&
                             this.eventTypeCheckers.includes(this.eventList[i].type) &&
-                            this.dropDownShowCondition(this.selectedEventStatusNow, this.eventList[i])
+                            this.dropDownShowCondition(this.selectedEventStatusNow.type, this.eventList[i])
                         ) {
                             currentfilterArray.push(this.eventList[i]);
                         }
                     }
                 }
                 if (currentfilterArray.length !== 0) {
-                    this.eventShow = [...currentfilterArray]
+                    if(this.nowTea) {
+                        this.eventShow = currentfilterArray.filter(item => item.creatorId === this.teachers[this.nowTea - 1].id)
+                    } else {
+                        this.eventShow = [...currentfilterArray]
+                    }
                     this.isListNoItem = false;
-                    document.querySelectorAll(".list .list-block")[0].scrollBy({
-                        top: -document.querySelectorAll(".list .list-block")[0]
+                    document.querySelectorAll(".event-list .list-block")[0].scrollBy({
+                        top: -document.querySelectorAll(".event-list .list-block")[0]
                             .scrollHeight,
                         behavior: "smooth",
                     });
@@ -754,15 +812,27 @@ import QuesNaire from "./EventContentTypeTemplate/QuesNaire";
                         item.allowRetryNow == true &&
                         item.isDone == false
                     );
-                } else if (status == "进行中") {
+                } else if (status == "going") {
                     return (
-                        item.progress == "going"
+                        item.stuProgress == "going"
                     );
                     this.hideIconbtn = false;
                     return item.isDone == false;
-                } else if (status == "已完成") {
+                } else if (status == "finish") {
+                    return (
+                        item.stuProgress == "finish"
+                    );
+                    this.hideIconbtn = false;
+                    return item.isDone == true;
+                } else if (status == "noScore") {
                     return (
-                        item.progress == "finish"
+                        item.stuProgress == "noScore"
+                    );
+                    this.hideIconbtn = false;
+                    return item.isDone == true;
+                } else if (status == "noAns") {
+                    return (
+                        item.stuProgress == "noAns"
                     );
                     this.hideIconbtn = false;
                     return item.isDone == true;
@@ -825,13 +895,16 @@ import QuesNaire from "./EventContentTypeTemplate/QuesNaire";
             scrollListfromInfoPop() {
                 if (this.getisFromInfoPoptoScroll == true) {
                     //當從通知操作進行捲動時,將篩選條件清空
-                    this.selectedEventStatusNow = this.$t('studentWeb.event.allStatus');
+                    this.selectedEventStatusNow = {
+                        type: "all",
+                        status: this.$t('studentWeb.event.allStatus')
+                    };
                     this.eventTypeCheckers = "";
                     let targetItem = document.getElementById(
                         `event${this.getItemTitle.eventID}`
                     );
                     let scrollList = document.querySelectorAll(
-                        ".list .list-block"
+                        ".event-list .list-block"
                     )[0];
 
                     if (scrollList !== undefined) {
@@ -987,6 +1060,17 @@ import QuesNaire from "./EventContentTypeTemplate/QuesNaire";
                 let time = (new Date(new Date(new Date(date).toLocaleDateString()).getTime())).getTime()
                 this.getActivityInfo(time)
             },
+            changeTea(index, teacher) {
+                this.nowTea = index
+                this.predealMockdatafirstItem()
+                /* if(teacher) {
+                    let list = this.eventShow.filter(item => item.creatorId === teacher.id)
+                    if (!list.length) {
+                        this.isListNoItem = true;
+                    }
+                    this.eventShow = list
+                } */
+            },
         },
         beforeDestroy () {
             clearInterval(this.countDown)

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

@@ -112,6 +112,7 @@
         } */
     };
 </script>
+
 <style scoped>
 .hide-sidebars {
     /*width: 0%;*/

+ 4 - 11
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventiView.less

@@ -1,17 +1,10 @@
 @import '~@/assets/student-web/component_styles/color.less';
 
-.event-selector-block {
-    padding: 17px 25px;
-
-    .list-title {
-        font-size: 18px;
-        text-decoration: none;
-        color: #515a6e;
-    }
+.event-list .event-selector-block {
 
     .icon-selector {
-        margin-top: 18px;
-        margin-bottom: 10px;
+        margin-top: 10px;
+        // margin-bottom: 10px;
 
         .ivu-checkbox-group .ivu-checkbox-wrapper .ivu-checkbox {
             display: none;
@@ -106,7 +99,7 @@
     }
 
     .ivu-select-dropdown {
-        width: 50% !important;
+        // width: 50% !important;
         border-radius: 4px !important;
         padding: 10px 0px;
 

+ 130 - 3
TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeView.less

@@ -25,8 +25,19 @@
         }
     }
 
+    .activity-box {
+        height: 455px;
+    }
+
+    .other-box {
+        height: 455px;
+    }
+
     .home-head {
         margin-top: 15px;
+        height: 315px;
+        overflow: hidden;
+        padding-bottom: 10px;
         // display: flex;
 
         .home-echarts {
@@ -42,6 +53,80 @@
         .exam-echarts {
             width: 30%;
         } */
+
+        .no-class {
+            font-size: 25px;
+            font-weight: bold;
+            text-align: center;
+            margin-top: 50px;
+            color: #64AE16;
+        }
+
+        .home-join {
+            height: calc(100% - 40px);
+            margin-bottom: 10px;
+        }
+
+        .join-class {
+            display: inline-block;
+            width: 18%;
+            border-radius: 10px;
+            border: 1px solid #e7f2ea;
+            padding: 10px;
+            margin: 5px 15px 10px;
+            cursor: pointer;
+            background-color: #e7f2ea;
+
+            .class-name {
+                // color: #02B35A;
+                font-size: 16px;
+                font-weight: bold;
+                overflow: hidden;
+                text-overflow: ellipsis;
+                white-space: nowrap;
+                margin-bottom: 10px;
+            }
+
+            .class-number-time {
+                display: flex;
+                justify-content: space-between;
+            }
+
+            .paper-item-school {
+                font-weight: bolder;
+                height: 20px;
+                line-height: 18px;
+                // padding: 5px 2px;
+                // margin-top: 10px;
+                // margin-right: 20px;
+                margin-bottom: 5px;
+                // cursor: pointer;
+                display: inline-flex;
+                font-size: 12px;
+
+                &>span {
+                    padding: 0 5px;
+                    white-space: pre;
+                }
+
+                .paper-owner {
+                    background-color: #ababab;
+                    color: #fff;
+                    border-radius: 5px 0 0 5px;
+                }
+
+                .paper-extType {
+                    border: 1px solid #ababab;
+                    border-radius: 0 5px 5px 0;
+                    border-left: none;
+                }
+
+                .paper-source {
+                    border: 1px solid #ababab;
+                    // border-radius: 0 5px 5px 0;
+                }
+            }
+        }
     }
 
     .no-data {
@@ -108,8 +193,50 @@
     }
 }
 
-@media screen and (max-width: 520px) {
-    .home-view .home-list-title {
-        display: block;
+@media screen and (max-width: 1280px) {
+    .home-view {
+        .home-list-title {
+            display: block;
+        }
+
+        .activity-box {
+            height: 305px;
+        }
+
+        .other-box {
+            height: 330px;
+        }
+
+        .home-head .join-class {
+            width: 30%;
+        }
+    }
+}
+
+@media screen and (max-width: 768px) {
+    .home-view {
+        .home-list-title {
+            display: flex;
+        }
+
+        .activity-box {
+            height: 305px;
+        }
+
+        .other-box {
+            height: 330px;
+        }
+
+        .home-head .join-class {
+            width: 45%;
+        }
+    }
+}
+
+@media screen and (max-width: 574px) {
+    .home-view {
+        .home-head .join-class {
+            width: 80%;
+        }
     }
 }

+ 788 - 0
TEAMModelOS/ClientApp/src/components/student-web/HomeView/newHomeView.vue

@@ -0,0 +1,788 @@
+<template>
+    <div class="home-view">
+        <Loading v-show="isLoading" bgColor="rgba(0, 0, 0, 0.3)"></Loading>
+        <div class="home-head home-card">
+            <p class="home-title-name">
+                {{ $t("studentWeb.home.title.joinClass") }}
+                <Icon type="md-add-circle" color="#02B35A" size="17" title="加入课程" @click="addCourse = true" v-if="getAllCourse.length" />
+            </p>
+            <div class="home-join" v-if="getAllCourse.length">
+                <vuescroll>
+                    <div class="join-class" v-for="(item, index) in getAllCourse" :key="index" @click="choiceClass(index)">
+                        <p class="class-name" :title="`${item.name} - ${item.listName}`">{{ item.name }} - {{ item.listName }}</p>
+                        <!-- <p class="paper-item-school">
+                            <span class="paper-owner" v-if="item.scope === 'school'" style="background-color: #88a1d8;">{{ $t('studentWeb.public.school') }}</span>
+                            <span class="paper-owner" v-else>{{ $t('studentWeb.public.private') }}</span>
+                            <span class="paper-extType">
+                                {{ item.teacherName }}
+                            </span>
+                        </p> -->
+                        <p class="class-number-time">
+                            <!-- <span>{{ '班级人数' }}</span> -->
+                            <span class="paper-item-school">
+                                <span class="paper-owner" v-if="item.scope === 'school'" style="background-color: #88a1d8;">{{ $t('studentWeb.public.school') }}</span>
+                                <span class="paper-owner" v-else>{{ $t('studentWeb.public.private') }}</span>
+                                <span class="paper-extType">
+                                    {{ item.teacherName }}
+                                </span>
+                            </span>
+                            <span>{{ item.courseAddDate }}</span>
+                        </p>
+                    </div>
+                </vuescroll>
+            </div>
+            <div class="no-class" v-else>
+                <p>{{ $t("studentWeb.home.title.title1") }}</p>
+                <p>{{ $t("studentWeb.home.title.title2") }}</p>
+            </div>
+        </div>
+        <Row :gutter="30">
+            <Col :xs="24" :sm="24" :md="24" :lg="12" :xl="8">
+                <div class="home-card">
+                    <p class="home-title-name">{{ $t("studentWeb.home.title.classRecord") }}</p>
+                    <div v-if="classRecord.length" class="other-box">
+                        <vuescroll>
+                            <div v-for="(classRecord, cIndex) in classRecord" :key="cIndex" class="list-new" @click="toRecord(classRecord)">
+                                <div class="list-new-img">
+                                    <img :src="classRecord.CoverImage ? classRecord.CoverImage : './noData.png'" alt="">
+                                </div>
+                                <div class="list-new-test">
+                                    <p>{{ classRecord.name }}</p>
+                                    <p class="list-item-time" style="color: #76ae38;">{{ classRecord.classNames }}</p>
+                                    <p class="list-item-time">{{ $t("studentWeb.public.uploadTime") }}:{{ classRecord.startTime }}</p>
+                                </div>
+                                <div class="list-new-type">
+                                    <p>
+                                        <Icon type="md-time" color="#24B880" />
+                                        {{ classRecord.time }}
+                                    </p>
+                                    <p style="color: #24B880;">
+                                        {{ $t("studentWeb.home.toLook") }}
+                                        <Icon type="md-arrow-round-forward" />
+                                    </p>
+                                </div>
+                            </div>
+                        </vuescroll>
+                    </div>
+                    <div v-else class="no-data">
+                        <img src="./noData.png" alt="">
+                        <p>{{ $t("studentWeb.public.noData") }}</p>
+                    </div>
+                </div>
+            </Col>
+            <Col :xs="24" :sm="24" :md="24" :lg="12" :xl="9">
+                <div class="home-card">
+                    <div class="home-list-title">
+                        <p class="home-title-name">{{ $t("studentWeb.home.title.activity") }}</p>
+                        <p>
+                            <span class="list-type">{{ $t("studentWeb.home.exam") }}:{{ activityType.exam }}</span>
+                            <span class="list-type">{{ $t("studentWeb.home.homework") }}:{{ activityType.homework }}</span>
+                            <span class="list-type">{{ $t("studentWeb.home.vote") }}:{{ activityType.vote }}</span>
+                            <span class="list-type">{{ $t("studentWeb.home.survey") }}:{{ activityType.survey }}</span>
+                        </p>
+                    </div>
+                    <div v-if="activityList.length" class="activity-box">
+                        <vuescroll>
+                            <div v-for="(activity, aIndex) in activityList" :key="aIndex" class="list-new" @click="sentSelectedEventTitle(activity)">
+                                <div class="list-new-icon">
+                                    <svg-icon v-if="activity.type == 'Homework'" icon-class="doc" color="#f0be72" />
+                                    <svg-icon v-if="activity.type == 'Exam'" color="#94a1e4" icon-class="test" class="reset-testIcon" />
+                                    <svg-icon v-if="activity.type == 'Vote'" icon-class="vote" color="#6a9a8b" />
+                                    <svg-icon v-if="activity.type == 'Survey'" icon-class="quesnaire" color="#d19f9c" />
+                                </div>
+                                <div class="list-new-test">
+                                    <div class="paper-item-school">
+                                        <span class="paper-owner" v-if="activity.owner === 'school'" style="background-color: #88a1d8;">{{ $t('studentWeb.public.school') }}</span>
+                                        <span class="paper-owner" v-else>{{ $t('studentWeb.public.private') }}</span>
+                                        <template v-if="activity.type == 'Exam'">
+                                            <span class="paper-extType" :style="{'border-color': activity.owner === 'school' ? '#88a1d8' :'#ababab'}" v-if="activity.source === '0'">
+                                                {{ $t("studentWeb.exam.source.evMode1") }}
+                                            </span>
+                                            <span class="paper-source" :style="{'border-color': activity.owner === 'school' ? '#88a1d8' :'#ababab', color: '#2f98a9'}" v-if="activity.source === '1'">
+                                                {{ $t("studentWeb.exam.source.evMode2") }}
+                                            </span>
+                                            <span class="paper-extType" :style="{'border-color': activity.owner === 'school' ? '#88a1d8' :'#ababab', color: '#b68268'}" v-if="activity.source === '2'">
+                                                {{ $t("studentWeb.exam.source.evMode3") }}
+                                            </span>
+                                            <!-- 课中评量才判断:qamode:0(书面问答),1(纸本测验) -->
+                                            <template v-if="activity.source === '1'">
+                                                <span class="paper-extType" :style="{'border-color': activity.owner === 'school' ? '#88a1d8' :'#ababab', color: '#b68268'}"
+                                                    v-if="activity.qamode"
+                                                >
+                                                    {{ $t("studentWeb.exam.source.evMode21") }}
+                                                </span>
+                                                <span class="paper-extType" :style="{'border-color': activity.owner === 'school' ? '#88a1d8' :'#ababab', color: '#b68268'}"
+                                                    v-else
+                                                >
+                                                    {{ $t("studentWeb.exam.source.evMode22") }}
+                                                </span>
+                                            </template>
+                                        </template>
+                                        <template v-else>
+                                            <span class="paper-extType">
+                                                {{ activity.type === 'Vote' ? $t('studentWeb.home.vote') : (activity.type === 'Survey' ? $t('studentWeb.home.survey') : $t('studentWeb.home.homework')) }}
+                                            </span>
+                                        </template>
+                                    </div>
+                                    <p class="list-item-title">
+                                        <span>{{ activity.name }}</span>
+                                    </p>
+                                    <p style="font-size:12px; margin-top: 5px; word-break: keep-all;">
+                                        <span v-if="activity.ext">
+                                            <span v-if="activity.ext.subjects">
+                                                <span v-for="(item, index) in activity.ext.subjects" :key="index" :title="item.name"
+                                                    style="border-color: #499c8d; color: #499c8d;" class="tag-style text-long"
+                                                >
+                                                    {{ item.name }}
+                                                </span>
+                                            </span>
+                                        </span>
+                                        <!-- <span v-if="activity.className.length">
+                                            <span v-for="(clasNa, index) in activity.className" :key="index" :title="clasNa"
+                                                style="border-color: #8f8787; color: #8f8787;" class="tag-style text-long"
+                                            >
+                                                {{ clasNa }}
+                                            </span>
+                                        </span> -->
+                                        <!-- <span class="tag-style text-long" style="border-color: #6b6ba9; color: #6b6ba9;"
+                                            v-if="activity.teacherName" :title="activity.teacherName"
+                                        >{{ activity.teacherName }}</span> -->
+                                    </p>
+                                    <p class="list-item-time">
+                                        {{ dateFormat(activity.startTime) }} ~ {{ dateFormat(activity.endTime) }}
+                                    </p>
+                                </div>
+                                <div class="list-new-type">
+                                    <span style="font-size: 12px; text-align: center;">{{ activity.tempsub }}</span>
+                                    <div class="list-new-unDone isAllowRetry">
+                                        <span>{{ $t("studentWeb.home.toLook") }}</span>
+                                    </div>
+                                </div>
+                            </div>
+                        </vuescroll>
+                    </div>
+                    <div v-else class="no-data">
+                        <img src="./noData.png" alt="">
+                        <p>{{ $t("studentWeb.public.noData") }}</p>
+                    </div>
+                </div>
+            </Col>
+            <Col :xs="24" :sm="24" :md="24" :lg="12" :xl="7">
+                <div class="home-card">
+                    <div>
+                        <div class="home-list-title">
+                            <p class="home-title-name">{{ $t("studentWeb.home.title.notice1") }}</p>
+                            <div class="select-time">
+                                <Select v-model="timeSelect" size="small" style="width: 100px;">
+                                    <Option value="all">{{ $t("studentWeb.home.timeType.title1") }}</Option>
+                                    <Option value="today">{{ $t("studentWeb.home.timeType.title2") }}</Option>
+                                </Select>
+                            </div>
+                        </div>
+                        <div class="other-box">
+                            <vuescroll>
+                                <div v-if="!allNotice.length" class="no-data-notice">
+                                    <img src="./noData.png" alt="">
+                                    <p>{{ $t("studentWeb.public.noData") }}</p>
+                                </div>
+                                <div v-else>
+                                    <div v-for="(cNotice, nIndex) in allNotice" :key="nIndex" class="list-new" @click="getNoticeInfo(cNotice)">
+                                        <div class="list-new-icon">
+                                            <Icon custom="iconfont icon-notify" size="30" />
+                                        </div>
+                                        <div class="list-new-test">
+                                            <p class="list-item-title">
+                                                <span>{{ cNotice.title }}</span>
+                                            </p>
+                                            <p>
+                                                {{ cNotice.content }}
+                                            </p>
+                                            <p class="list-item-time">
+                                                {{ cNotice.start }} ~ {{ cNotice.end }}
+                                            </p>
+                                        </div>
+                                    </div>
+                                </div>
+                            </vuescroll>
+                        </div>
+                    </div>
+                </div>
+            </Col>
+        </Row>
+        <Modal v-model="showNotice" :title="nowNotice ? nowNotice.title : ''" width="800">
+            <template v-if="nowNotice">
+                <p>{{ nowNotice.content }}</p>
+            </template>
+        </Modal>
+        <!-- 添加课程 -->
+        <Modal v-model="addCourse" title="加入您想学习的课程" mask-closable>
+            <Input v-special-char clearable v-model="addClassNo" :placeholder="$t('studentWeb.home.classPla')">
+                <Button slot="append" @click="addClass">{{ $t('studentWeb.home.joinClass') }}</Button>
+            </Input>
+            <div slot="footer"></div>
+        </Modal>
+    </div>
+</template>
+
+<script>
+import ExamPerform from './ChartHome/ExamPerform.vue';
+import HomeworkPoint from './ChartHome/HomeworkPoint.vue';
+import ClassPoint from './ChartHome/ClassPoint.vue';
+
+import { mapGetters, mapState } from 'vuex';
+import BlobTool from "@/utils/blobTool.js"
+
+export default {
+    name: "HomeViewnnnnew",
+    components: {
+        ExamPerform,
+        HomeworkPoint,
+        ClassPoint,
+    },
+    // inject: ['reload'],
+    data() {
+        return {
+            MyNo: "1", //接收NavBar 選定的那一頁icon標示
+            MyName: "",
+            isLoading: false,
+            classRecord: [], //课堂记录
+            activityList: [], //活动
+            classNotice: [], //班级公告
+            courseNotice: [], //课程公告
+            allNotice: [],
+            countDown: null,
+            activityType: {
+                exam: 0,
+                homework: 0,
+                vote: 0,
+                survey: 0,
+            },
+            examAch: [],
+            groups: {
+                school: [],
+                private: [],
+            },
+            sasInfo: undefined,
+            classIds: [],
+            showNotice: false,
+            nowNotice: undefined,
+            addCourse: false,
+            addClassNo: '',
+            timeSelect: "all",
+        }
+    },
+    mounted () {
+        this.MyName = this.$t("studentWeb.homeViewTitle")
+        this.$emit("onNavNo", this.MyNo)
+        this.$emit("onNavName", this.MyName)
+        this.getGroupList()
+        this.getActivity()
+    },
+    methods: {
+        getNotice(classes) {
+            this.classNotice = []
+            this.courseNotice = []
+            this.$api.studentWeb.getAllNotice({classes}).then(async res => {
+                // type:class(班级公告)  course(课程公告)
+                if(res.notices.length) {
+                    let teaIds = []
+                    res.notices.forEach(item => {
+                        teaIds.push(item.creatorId)
+                    })
+                    let teaidNames = await this.getTeacherName(teaIds)
+                    res.notices.forEach(item => {
+                        item.start = this.dateFormat(item.startTime)
+                        item.end = this.dateFormat(item.endTime)
+                        item.className = []
+                        item.classes.forEach(classes => {
+                            let names = this.classIds.find(ids => {
+                                return ids.id === classes
+                            })
+                            if(names) {
+                                item.className.push(names.name)
+                            }
+                        })
+                        let nameIds = teaidNames.find(names => {
+                            return names.id === item.creatorId
+                        })
+                        item.teacherName = !nameIds ? undefined : nameIds.name
+                        if(item.type === "class") {
+                            this.classNotice.push(item)
+                        } else {
+                            this.courseNotice.push(item)
+                        }
+                        this.allNotice = this.classNotice.concat(this.courseNotice)
+                    })
+                }
+            })
+        },
+        getGroupList() {
+            // return new Promise(resolve => {
+                this.isLoading = true
+                this.groups = {
+                    school: [],
+                    private: [],
+                }
+                this.classRecord = []
+                // this.getSas(this.userInfo.azp)
+                this.$api.studentWeb.getAllGrouplist({}).then(res => {
+                    if(res.groups.length) {
+                        let groupIds = []
+                        this.classIds = [...res.groups]
+                        res.groups.forEach(item => {
+                            if(item.scope === 'school') {
+                                this.groups.school.push(item.id)
+                            } else if(item.scope === 'private') {
+                                this.groups.private.push(item.id)
+                            }
+                            groupIds.push(item.id)
+                        })
+                        this.getSchool("school", this.groups.school)
+                        this.getNotice(groupIds)
+                    }
+                }).finally(() => {
+                    // resolve(groups)
+                })
+            // })
+        },
+        getSchool(type, groupIds, end) {
+            if(groupIds.length) {
+                let param = {
+                    scope: type, //school:传school,private:传tmdid
+                    school: type === "school" ? this.userInfo.azp : "",
+                    category: [],
+                    subjectId: [],
+                    grade: [],
+                    doubleGreen: false,
+                    quality: false,
+                    DESC: "startTime",
+                    pageCount: 999, //返回六条数据(分页)
+                    week: true,
+                    // today: false,
+                    continuationToken: null, //返回的有值的话,下次查询就要用这个值
+                    groupIds,
+                }
+                this.$api.studentWeb.getClassRecord(param).then(async res => {
+                    if(res.lessonRecords.length) {
+                        let creatId = []
+                        let sasInfo = undefined
+                        if(type === "school") {
+                            sasInfo = await this.getSas(this.userInfo.azp)
+                        }
+                        res.lessonRecords.forEach(item => {
+                            item.startTime = this.dateFormat(item.startTime)
+                            let sec = item.duration % 60
+                            let min = parseInt(item.duration / 60)
+                            let mins = min >= 60 ? min % 60 : min
+                            let hour = parseInt(min / 60)
+                            item.time = `${hour < 10 ? ('0' + hour) : hour}:${mins < 10 ? ('0' + mins) : mins}:${sec < 10 ? ('0' + sec) : sec}`
+                            if(type === "school") {
+                                item.eNote = `${sasInfo.url}/${sasInfo.name}/records/${item.id}/Note.pdf?${sasInfo.sas}`
+                                item.CoverImage = `${sasInfo.url}/${sasInfo.name}/records/${item.id}/Record/CoverImage.jpg?${sasInfo.sas}`
+                            } else {
+                                if(!creatId.includes(item.tmdid)) {
+                                    creatId.push(item.tmdid)
+                                }
+                                item.eNote = ""
+                                item.CoverImage = ""
+                            }
+                            let className = this.getAllCourse.find(course => {
+                                return item.courseId === course.id || item.courseId === course.subject.id
+                            })
+                            item.classNames = className ? className.name : ""
+                            item.myNote = []
+                            this.classRecord.push(item)
+                        })
+                        if(type === "private") {
+                            creatId.forEach(async item => {
+                                let sasInfoP = await this.getSas(item)
+                                this.classRecord = this.classRecord.map(record => {
+                                    if(record.scope === "private" && record.tmdid === item) {
+                                        record.eNote = `${sasInfoP.url}/${sasInfoP.name}/records/${record.id}/Note.pdf?${sasInfoP.sas}`
+                                        record.CoverImage = `${sasInfoP.url}/${sasInfoP.name}/records/${record.id}/Record/CoverImage.jpg?${sasInfoP.sas}`
+                                    }
+                                    return record
+                                })
+                                await this.getTrainFiles(sasInfoP, "private")
+                            })
+                        } else {
+                            this.getTrainFiles(sasInfo, "school")
+                        }
+                    }
+                    if(!end) {
+                        this.getSchool("private", this.groups.private, true)
+                    }
+                }).finally(() => {
+                    this.isLoading = false
+                })
+            } else if(!end) {
+                this.getSchool("private", this.groups.private, true)
+            }
+        },
+        // 查找活动的视频和文件
+        getTrainFiles(sasInfo, scope) {
+            return new Promise((r, j) => {
+                let blobTool = new BlobTool(sasInfo.url, sasInfo.name, "?" + sasInfo.sas, scope)
+                let promiseArr = []
+                let recList = [...this.classRecord]
+                if(scope === "school") {
+                    recList.forEach((item, index) => {
+                        promiseArr.push(new Promise((r, j) => {
+                            blobTool.listBlob({
+                                prefix: `records/${item.id}/Clients/${this.userInfo.sub}/Task/NoteSelfNote`
+                            }).then(
+                                res => {
+                                    let imgList = []
+                                    res.blobList.forEach(list => {
+                                        imgList.push(`${list.url}?${sasInfo.sas}`)
+                                    })
+                                    this.classRecord[index].myNote = imgList
+                                    r(res)
+                                },
+                                err => {
+
+                                }
+                            )
+                        }))
+                    })
+                } else {
+                    recList.forEach((item, index) => {
+                        if(item.scope === "private" && item.tmdid === sasInfo.name) {
+                            promiseArr.push(new Promise((r, j) => {
+                                blobTool.listBlob({
+                                    prefix: `records/${item.id}/Clients/${this.userInfo.sub}/Task/NoteSelfNote`
+                                }).then(
+                                    res => {
+                                        let imgList = []
+                                        res.blobList.forEach(list => {
+                                            imgList.push(`${list.url}?${sasInfo.sas}`)
+                                        })
+                                        this.classRecord[index].myNote = imgList
+                                        r(res)
+                                    },
+                                    err => {
+
+                                    }
+                                )
+                            }))
+                        }
+                    })
+                }
+                Promise.all(promiseArr).then(res => {
+                })
+            })
+        },
+        getSas(info) {
+            return new Promise(async (r, j) => {
+                let code = info
+                let sasInfo = await this.$tools.getBlobSas(code)
+                r(sasInfo)
+            })
+        },
+        getActivity(time) {
+            this.isLoading = true
+            // this.testData = []
+            // this.voteandSur = []
+            // this.examandHw = []
+            let params = {
+                userid: this.userInfo.sub,
+                userType: "",
+                school: this.userInfo.azp
+            }
+            // 醍摩豆登陆——> roles有teacher
+            params.userType = this.userInfo.scope === "tmduser" ? "tmdid" : "schoolid"
+            if(time) {
+                params.stime = time
+            }
+            this.$api.studentWeb.getActivityInfo(params).then(async res => {
+                if (res.datas.length) {
+                    let data = []
+                    let ids = []
+                    let teaIds = []
+                    let datasss = res.datas.filter(item => {
+                        item.progress = this.timeStatus(item, true)
+                        return item.progress === 'going'
+                    })
+                    datasss.forEach(item => {
+                        ids.push(item.classIds)
+                        teaIds.push(item.creatorId)
+                    })
+                    let teaidNames = []
+                    teaidNames = await this.getTeacherName(teaIds)
+                    ids = [].concat.apply([], ids)
+                    let names = ids.length ? await this.getClassName(ids, true) : []
+                    for (let item of datasss) {
+                        item.className = []
+                        item.classIds.forEach(classId => {
+                            let arr = names.filter(na => {
+                                return na.id === classId
+                            })
+                            if(arr.length) {
+                                item.className.push(arr[0].name)
+                            }
+                        });
+                        item.tempsub = ""
+                        let nameIds = undefined
+                        nameIds = teaidNames.find(names => {
+                            return names.id === item.creatorId
+                        })
+                        item.teacherName = !nameIds ? undefined : nameIds.name
+                        this.activityList.push(item)
+                        if(item.type === 'Exam') {
+                            this.activityType.exam += 1
+                        } else if(item.type === 'Homework') {
+                            this.activityType.homework += 1
+                        } else if(item.type === 'Vote') {
+                            this.activityType.vote += 1
+                        } else if(item.type === 'Survey') {
+                            this.activityType.survey += 1
+                        }
+                    }
+                    // this.activityList = [...data]
+                    let twoDay = 24 * 3600 * 1000 * 2
+                    this.countDown = setInterval(() => {
+                        let timeNow = new Date()
+                        for (const item of this.activityList) {
+                            let timeSub = item.endTime - timeNow
+                            item.tempsub = (item.taskStatus === -1 && timeSub > 0 && timeSub < twoDay) ? this.getTimeSub(timeSub) : ""
+                        }
+                    }, 1000)
+                    this.$forceUpdate()
+                }
+            }).finally(()=>{
+                this.isLoading = false
+            })
+        },
+        getClassName(ids, type) {
+            return new Promise((r, j) => {
+                let params = {ids}
+                if(type) {
+                    params.schoolId = this.userInfo.azp
+                }
+                this.$api.learnActivity.getClassNameByIds(params).then(res => {
+                    if(res.groups) {
+                        r(res.groups)
+                    } else {
+                        r([])
+                    }
+                }).catch(e => {
+                    j(e)
+                })
+            })
+        },
+        timeStatus(data, type) {
+            // type:只获取活动是否结束
+            let date = (new Date()).getTime() //当前时间
+            if (date >= data.endTime) {
+                if(type) {
+                    return 'finish'
+                } else if(data.type != 'Exam'){
+                    return 'finish'
+                } else {
+                    // 线上评测、未作答
+                    if(data.taskStatus === -1 && data.source === '0') {
+                        // 缺考
+                        return 'noAns'
+                    } else if(!data.sStatus) {
+                        // 以前的sStatus都为0,所以全是未评分
+                        // 未评分
+                        return 'noScore'
+                    } else {
+                        // 已结束
+                        return 'finish'
+                    }
+                }
+            } else {
+                return 'going'
+            }
+        },
+        //时间格式化处理
+        dateFormat(timestamp) {
+            var date = new Date(timestamp)
+            var Y = date.getFullYear() + '-'
+            var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-'
+            var D = (date.getDate() < 10 ? '0' + (date.getDate()) : date.getDate()) + ' '
+            var H = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ":"
+            var Min = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes())
+            var S = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()) + " "
+            return Y + M + D + H + Min;
+        },
+        getTimeSub(sub) {
+            // 天数
+            var days = Math.floor(sub / (24 * 3600 * 1000))
+            // 小时
+            var leave1 = sub % (24 * 3600 *1000)
+            var hours = Math.floor(leave1 / (3600 * 1000))
+            if(hours < 10) {
+                hours = "0" + hours
+            }
+            // 分钟
+            var leave2 = leave1 % (3600 * 1000)
+            var minutes = Math.floor(leave2 / (60 * 1000))
+            if(minutes < 10) {
+                minutes = "0" + minutes
+            }
+            // 秒
+            var leave3 = leave2 % (60 * 1000);
+            var seconds = Math.round(leave3 / 1000);
+            if (seconds < 10) {
+                seconds = "0" + seconds;
+            }
+            
+            return (days ? (days + this.$t("studentWeb.public.day")) : '') + hours + this.$t("studentWeb.public.hour") + minutes + this.$t("studentWeb.public.minute")
+        },
+        getTeacherName(id) {
+            return new Promise((r, j) => {
+                this.$api.studentWeb.getTeacherName({id}).then(res => {
+                    r(res)
+                }).catch(e => {
+                    j(e)
+                })
+            })
+        },
+        sentSelectedEventTitle(item) {
+            let index =  this.getCourseIndex(item.subjects)
+            this.$EventBus.$emit('classIndex', index + 1)
+            let path = item.type === 'Exam' ? '/studentWeb/examView' : (item.type === 'Homework' ? '/studentWeb/homeworkView' : '/studentWeb/eventView')
+            this.$router.push({
+                path,
+                query: {aId: item.id}
+            })
+        },
+        toRecord(item) {
+            let index =  this.getCourseIndex([item.courseId])
+            this.$EventBus.$emit('classIndex', index + 1)
+            this.$router.push({
+                path: "/studentWeb/classRecord",
+                query: {aId: item.id}
+            })
+        },
+        getNoticeInfo(info) {
+            this.showNotice = true
+            this.nowNotice = info
+        },
+        choiceClass(index) {
+            // this.$parent.classChange(index + 1)
+            this.$store.commit("setNowCourse", undefined)
+            this.$EventBus.$emit('classIndex', index + 1)
+        },
+        // 加入课程
+        addClass() {
+            if (this.addClassNo) {
+                let isStu = this.userInfo.scope != "tmduser"
+                let req = {
+                    stuListNo: this.addClassNo,
+                    studentId: "",
+                    tmdId: ""
+                }
+                if (isStu) {
+                    req.studentId = this.userInfo.sub
+                } else {
+                    req.tmdId = this.userInfo.sub
+                }
+                this.$api.studentWeb.getAddClass(req).then(res => {
+                    // -1 课程编码错误,0加入成功,1参数异常,2重复加入,4表示个人名单未开放加入 
+                    if (res.status == 0) {
+                        this.$Message.success(this.$t('studentWeb.courseType.success'))
+                        this.addClassNo = ""
+                        this.addCourse = false
+                        this.$parent.getNameByHome()
+                    } else if (res.status == 2) {
+                        this.$Message.warning(this.$t('studentWeb.courseType.warning'))
+                    } else if (res.status == -1) {
+                        this.$Message.warning(this.$t('studentWeb.courseType.error'))
+                    } else if (res.status === 4) {
+                        this.$Message.warning(this.$t('studentWeb.courseType.noAgree'))
+                    } else {
+                        this.$Message.error(this.$t('studentWeb.courseType.api'))
+                    }
+                })
+            }
+        },
+        getCourseIndex(ids) {
+            return this.getAllCourse.findIndex(course => {
+                return ids.includes(course.id) || ids.includes(course.subject.id)
+            })
+        },
+    },
+    computed: {
+        ...mapState({
+            userInfo: state => state.userInfo,
+        }),
+        ...mapGetters(['getAllCourse'])
+    },
+    watch: {
+        getAllCourse: {
+            handler(n, o) {
+                if(this.classRecord) {
+                    let recordList = [...this.classRecord]
+                    this.classRecord = recordList.map(item => {
+                        let className = n.find(course => {
+                            return item.courseId === course.id || item.courseId === course.subject.id
+                        })
+                        item.classNames = className ? className.name : ""
+                        return item
+                    })
+                }
+            },
+            deep: true,
+        },
+        timeSelect: {
+            handler(n, o) {
+                if(n === 'today') {
+                    let time = new Date(new Date().toLocaleDateString()).getTime();
+                    let tiem24 = new Date(new Date().toLocaleDateString()).getTime() + 24 * 60 * 60 * 1000 - 1
+                    this.allNotice = []
+                    let gNotice = [...this.classNotice]
+                    let cNotice = [...this.courseNotice]
+                    gNotice.forEach(item => {
+                        if(item.endTime > time && item.endTime < tiem24) {
+                            this.allNotice.push(item)
+                        }
+                    })
+                    cNotice.forEach(item => {
+                        if(item.endTime > time && item.endTime < tiem24) {
+                            this.allNotice.push(item)
+                        }
+                    })
+                } else {
+                    this.allNotice = []
+                    this.allNotice = this.classNotice.concat(this.courseNotice)
+                }
+            },
+            deep: true,
+        },
+    },
+    beforeDestroy () {
+        clearInterval(this.countDown)
+        this.countDown = null
+    },
+}
+</script>
+
+<style lang="less" scoped>
+@import './HomeView.less';
+@import "~@/assets/student-web/component_styles/event-list-new.less";
+</style>
+
+<style lang="less">
+.home-view {
+    .home-title-name {
+        font-size: 16px;
+        border-left: 5px solid #24b880;
+        padding-left: 10px;
+        height: 20px;
+        line-height: 20px;
+        margin-bottom: 10px;
+    }
+
+    .select-time {
+        
+        .ivu-select-selection {
+            border-radius: 15px;
+            background-color: #eaeaea;
+            border-color: #eaeaea;
+        }
+    }
+}
+</style>

+ 26 - 0
TEAMModelOS/ClientApp/src/components/student-web/StudyView/StudyList.less

@@ -0,0 +1,26 @@
+.study-view {
+    .layout-left-wrap {
+        padding-left: 10px;
+    }
+
+    .ivu-tree ul {
+        font-size: 15px;
+        font-weight: 700;
+    }
+
+    .ivu-tree-arrow,
+    .ivu-tree-title {
+        height: 40px;
+        line-height: 40px;
+    }
+
+    .ivu-tree-title {
+        width: 93%;
+        padding-left: 10px;
+    }
+
+    .ivu-tree-title-selected,
+    .ivu-tree-title:hover {
+        background-color: #DFF0E8;
+    }
+}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 344 - 0
TEAMModelOS/ClientApp/src/components/student-web/StudyView/StudyViews.vue


+ 4 - 4
TEAMModelOS/ClientApp/src/components/student-web/WrongQusetion/WrongQues.vue

@@ -117,7 +117,7 @@ export default {
     name: "",
     data () {
         return {
-            MyNo: "4",
+            MyNo: "8",
             MyName: "",
             animal: "",
             filtSubject: 0,
@@ -298,12 +298,12 @@ export default {
             this.pageChange(1)
         },
         startPra() {
-            this.$router.push({
-                name: "eventView/evaluation",
+            // this.$router.push({
+            //     name: "eventView/evaluation",
                 /* params: {
                     papers: this.paperInfo
                 } */
-            })
+            // })
         },
     },
     computed: {

+ 115 - 94
TEAMModelOS/ClientApp/src/components/student-web/achievement/MyAchievement.vue

@@ -1,7 +1,7 @@
 <template>
     <div class="achievement-report">
         <Loading v-show="isLoading" bgColor="rgba(0, 0, 0, 0.3)"></Loading>
-        <Tabs value="exam">
+        <Tabs :value="achievement">
             <TabPane :label="$t('studentWeb.myAchievement.examAch')" name="exam">
                 <div class="report-head student-check">
                     <div class="filter-type">
@@ -132,13 +132,14 @@
             <TabPane :label="$t('studentWeb.myAchievement.cusAch')" name="classrecord">
                 <div>
                     <div class="report-head student-check">
-                        <div>
+                        <!-- <div>
                             <span class="type-name">{{ $t("studentWeb.baseInfo.subjectName") }}:</span>
                             <Select v-model="recordType.classes" filterable clearable style="width:200px">
                                 <Option v-for="item in courseList" :value="item.id" :key="item.id">{{ item.name }}</Option>
                             </Select>
-                        </div>
-                        <div v-if="semester.length" class="semester-type">
+                        </div> -->
+                        <!-- <div v-if="semester.length" class="semester-type"> -->
+                        <div v-if="semester.length">
                             <span class="type-name">{{ $t("studentWeb.myAchievement.semesters") }}:</span>
                             <!-- 调接口获取当前学校的学期信息 -->
                             <Select v-model="recordType.semester" clearable style="width:200px">
@@ -162,13 +163,14 @@
 </template>
 
 <script>
-import { mapState } from 'vuex';
+import { mapGetters, mapState } from 'vuex';
 export default {
     name: "MyAchievement",
     data () {
         return {
             MyNo: "7",
             MyName: this.$t('studentWeb.type.achievement'),
+            achievement: "exam",
             isLoading: false,
             examCol: [
                 {
@@ -508,10 +510,11 @@ export default {
             let param = {
                 continuationToken: this.continuationTokenRecord,
                 count: 20,
+                courseId: this.courseNow.id
             }
-            if(this.recordType.classes !== undefined) {
+            /* if(this.recordType.classes !== undefined) {
                 param.courseId = this.recordType.classes
-            }
+            } */
             if(this.recordType.semester !== undefined) {
                 param.stime = this.semester[this.recordType.semester].stime
                 param.etime = this.semester[this.recordType.semester].etime
@@ -607,66 +610,78 @@ export default {
                         let teaName = teaId.length ? await this.getTeacherName(teaId) : []
                         res.result.forEach(result => {
                             let examData = {...result}
-                            examData.startTime = this.dateFormat(result.time)
-                            let nameIds = teaName.find(names => {
-                                return names.id === result.createId
+                            let hasCourse = false
+                            // 先匹配课程和名单
+                            examData.subject.forEach((sub, index) => {
+                                if(sub.id === this.courseNow.id || sub.id === this.courseNow.subject.id) {
+                                    if(examData.result[index + index * examData.point.length].cId === this.courseNow.list) {
+                                        hasCourse = true
+                                    }
+                                }
                             })
-                            examData.creator = !nameIds ? undefined : nameIds.name
-                            examData.type = ""
-                            examData.total = 0
-                            examData.class = []
-                            if(result.ext) {
-                                examData.subjects = result.ext.subjects ? result.ext.subjects : []
-                                examData.type = result.ext.type
-                            }
-                            if(result.result.length) {
-                                result.result.forEach(score => {
-                                    // 当前班级是否有本人,有才加入examData.class
-                                    let myId = score.sIds.findIndex(sId => {
-                                        return sId === this.userInfo.sub
-                                    })
-                                    if(myId != -1) {
-                                        // examData.class有值,判断当前班级是否存在
-                                        if(examData.class.length) {
-                                            let haveCid = examData.class.find(myClass => {
-                                                return myClass.cId === score.cId
-                                            })
-                                            if(!haveCid) {
+                            if(hasCourse) {
+                                examData.startTime = this.dateFormat(result.time)
+                                let nameIds = teaName.find(names => {
+                                    return names.id === result.createId
+                                })
+                                examData.creator = !nameIds ? undefined : nameIds.name
+                                examData.type = ""
+                                examData.total = 0
+                                examData.class = []
+                                if(result.ext) {
+                                    examData.subjects = result.ext.subjects ? result.ext.subjects : []
+                                    examData.type = result.ext.type
+                                }
+                                if(result.result.length) {
+                                    result.result.forEach(score => {
+                                        // 当前班级是否有本人,有才加入examData.class
+                                        let myId = score.sIds.findIndex(sId => {
+                                            return sId === this.userInfo.sub
+                                        })
+                                        if(myId != -1) {
+                                            // examData.class有值,判断当前班级是否存在
+                                            if(examData.class.length) {
+                                                let haveCid = examData.class.find(myClass => {
+                                                    return myClass.cId === score.cId
+                                                })
+                                                if(!haveCid) {
+                                                    examData.class.push({
+                                                        cId: score.cId,
+                                                        cname: score.cname
+                                                    })
+                                                }
+                                            } else {
                                                 examData.class.push({
                                                     cId: score.cId,
                                                     cname: score.cname
                                                 })
                                             }
-                                        } else {
-                                            examData.class.push({
-                                                cId: score.cId,
-                                                cname: score.cname
-                                            })
-                                        }
-                                        if(examData.subjects.length) {
-                                            // 查找当前科目
-                                            let subjIn = examData.subjects.findIndex(subj => {
-                                                return subj.id === score.sub
-                                            })
-                                            if(subjIn != -1) {
-                                                examData.subjects[subjIn].score = score.sum[myId]
+                                            if(examData.subjects.length) {
+                                                // 查找当前科目
+                                                let subjIn = examData.subjects.findIndex(subj => {
+                                                    return subj.id === score.sub
+                                                })
+                                                if(subjIn != -1) {
+                                                    examData.subjects[subjIn].score = score.sum[myId]
+                                                }
+                                            } else {
+                                                examData.subjects.push({
+                                                    id: score.sub,
+                                                    name: null,
+                                                    score: 0
+                                                })
                                             }
-                                        } else {
-                                            examData.subjects.push({
-                                                id: score.sub,
-                                                name: null,
-                                                score: 0
-                                            })
                                         }
-                                    }
-                                })
-                                let totalScore = 0
-                                examData.subjects.forEach(subje => {
-                                    totalScore += (subje.score ? subje.score : 0)
-                                })
-                                examData.total = totalScore
+                                    })
+                                    let totalScore = 0
+                                    examData.subjects.forEach(subje => {
+                                        totalScore += (subje.score ? subje.score : 0)
+                                    })
+                                    examData.total = totalScore
+                                }
+                                this.examRep.push(examData)
                             }
-                            this.examRep.push(examData)
+                            
                         })
                     }
                 }
@@ -696,46 +711,48 @@ export default {
                     })
                     let teaName = teaId.length ? await this.getTeacherName(teaId) : []
                     res.works.forEach(work => {
-                        let hwData = {
-                            id: work.id,
-                            name: work.name,
-                            startTime: this.dateFormat(work.time),
-                            score: 0,
-                            star: 0,
-                            creator: null,
-                            replies: [],
-                            stuStar: 0,
-                        }
-                        let nameIds = teaName.find(names => {
-                            return names.id === work.createId
-                        })
-                        hwData.creator = !nameIds ? undefined : nameIds.name
-                        if(work.score.length && work.score[0].comments.length) {
-                            hwData.score = work.score[0].score
-                            let comments = work.score[0].comments.find(item => {
-                                return item.identity === 'teacher'
+                        if(work.cIds.includes(this.courseNow.list)) {
+                            let hwData = {
+                                id: work.id,
+                                name: work.name,
+                                startTime: this.dateFormat(work.time),
+                                score: 0,
+                                star: 0,
+                                creator: null,
+                                replies: [],
+                                stuStar: 0,
+                            }
+                            let nameIds = teaName.find(names => {
+                                return names.id === work.createId
                             })
-                            if(comments) {
-                                hwData.star = comments.star
-                                work.comment.forEach(comment => {
-                                    comment.reply.forEach(reply => {
-                                        if(comments.replyIds.includes(reply.id)){
-                                            hwData.replies.push(reply.comment)
-                                        }
+                            hwData.creator = !nameIds ? undefined : nameIds.name
+                            if(work.score.length && work.score[0].comments.length) {
+                                hwData.score = work.score[0].score
+                                let comments = work.score[0].comments.find(item => {
+                                    return item.identity === 'teacher'
+                                })
+                                if(comments) {
+                                    hwData.star = comments.star
+                                    work.comment.forEach(comment => {
+                                        comment.reply.forEach(reply => {
+                                            if(comments.replyIds.includes(reply.id)){
+                                                hwData.replies.push(reply.comment)
+                                            }
+                                        })
                                     })
+                                }
+                                let starTotal = 0
+                                let starNum = 0
+                                work.score[0].comments.forEach(item => {
+                                    if(item.identity === 'student') {
+                                        starTotal += item.star
+                                        starNum += 1
+                                    }
                                 })
+                                hwData.stuStar = starNum ? (Number((starTotal / starNum).toFixed(1))) : 0
                             }
-                            let starTotal = 0
-                            let starNum = 0
-                            work.score[0].comments.forEach(item => {
-                                if(item.identity === 'student') {
-                                    starTotal += item.star
-                                    starNum += 1
-                                }
-                            })
-                            hwData.stuStar = starNum ? (Number((starTotal / starNum).toFixed(1))) : 0
+                            this.homeworkRep.push(hwData)
                         }
-                        this.homeworkRep.push(hwData)
                     })
                     let total = 0
                     this.homeworkRep.forEach(item => {
@@ -864,7 +881,11 @@ export default {
     computed: {
         ...mapState({
             userInfo: state => state.userInfo,
-        })
+        }),
+        ...mapGetters(["getNowCourse"]),
+        courseNow() {
+            return this.getNowCourse || JSON.parse(decodeURIComponent(localStorage.course, "utf-8"))
+        },
     }
 }
 </script>

+ 77 - 0
TEAMModelOS/ClientApp/src/components/student-web/achievement/SchoolReport.less

@@ -0,0 +1,77 @@
+@import '~@/assets/student-web/component_styles/color.less';
+
+.report-head {
+    display: flex;
+    justify-content: space-between;
+
+    .base-info {
+        display: flex;
+        flex-direction: column;
+        align-items: flex-start;
+        margin-right: 50px;
+        padding-top: 1%;
+
+        & > span {
+            margin-bottom: 5px;
+        }
+    }
+
+    .filter-type{
+        padding: 1%;
+        margin-bottom: 20px;
+
+        & > div{
+            margin-bottom: 12px;
+
+            &:last-child {
+                margin-bottom: 0;
+                // margin-top: 10px;
+            }
+        }
+
+        .type-name {
+            margin-right: 10px;
+            font-weight: bold;
+        }
+        
+        .point-box {
+            border: 1px solid #24B880;
+            background-color: @primary;
+            color: #fff;
+            padding: 3px 5px;
+            border-radius: 5px;
+            margin-right: 10px;
+            display: inline-block;
+
+            .ivu-icon{
+                cursor: pointer;
+                margin-left: 5px;
+            }
+        }
+
+        .ivu-icon-md-add-circle {
+            // font-weight: bold;
+            cursor: pointer;
+        }
+
+        .have-total {
+            display: inline-block;
+            float: right;
+
+            & > span{
+                font-size: 18px;
+                font-weight: bold;
+                color: #de0000;
+                margin: 0 5px;
+            }
+        }
+    }
+}
+
+.tag-style {
+    border: 1px solid;
+    padding: 0 5px;
+    border-radius: 3px;
+    margin-right: 10px;
+    font-size: 12px;
+}

+ 324 - 0
TEAMModelOS/ClientApp/src/components/student-web/achievement/SchoolReport.vue

@@ -0,0 +1,324 @@
+<template>
+    <div class="achievement-report">
+        <div class="report-head student-check">
+            <div class="filter-type">
+                <div>
+                    <span class="type-name">{{ $t('studentWeb.baseInfo.examMode') }}:</span>
+                    <RadioGroup v-model="filterType.sourceType" type="button" button-style="solid">
+                        <Radio v-for="(item, index) in sourceTypeList" :key="index" :label="item.type">{{ item.name }}</Radio>
+                    </RadioGroup>
+                </div>
+                <!-- <div>
+                    <span class="type-name">{{ $t('studentWeb.baseInfo.examStatus') }}:</span>
+                    <RadioGroup v-model="examType" type="button" button-style="solid">
+                        <Radio v-for="(item, index) in examTypeList" :key="index + 1" :label="item.type">{{ item.name }}</Radio>
+                    </RadioGroup>
+                </div> -->
+                <div>
+                    <span class="type-name">{{ $t('studentWeb.baseInfo.examStatus') }}:</span>
+                    <RadioGroup v-model="filterType.ownerType" type="button" button-style="solid">
+                        <Radio v-for="(item, index) in ownerTypeList" :key="index" :label="item.type">{{ item.name }}</Radio>
+                    </RadioGroup>
+                </div>
+            </div>
+            <p class="base-info">
+                <span v-if="courseNow.teacherName">
+                    <Icon type="ios-contact-outline" style="font-weight: bold; margin-right: 5px;" />{{ $t('studentWeb.baseInfo.teacher') }}
+                    <span class="base-info-text">{{ courseNow.teacherName }}</span>
+                </span>
+                <span v-if="courseNow.name">
+                    <Icon custom="iconfont icon-mingdan" style="font-weight: bold; margin-right: 5px;" />{{ $t('studentWeb.baseInfo.subjectName') }}
+                    <span class="base-info-text">{{ courseNow.name }}</span>
+                </span>
+                <span>
+                    <Icon type="ios-contact-outline" style="font-weight: bold; margin-right: 5px;" />{{ $t('studentWeb.baseInfo.nowStu') }}
+                    <span class="base-info-text">{{ $store.state.userInfo.name }}</span>
+                </span>
+            </p>
+        </div>
+        <!-- <Table :columns="schoolRepCol" :data="showSchoolRep" :span-method="handleSpan"> -->
+        <Table :columns="schoolRepCol" :data="showSchoolRep" height="550">
+            <template slot-scope="{ row }" slot="tag">
+                <!-- <p>{{ row.name }}</p> -->
+                <span class="tag-style">{{ row.tag.owner === 'school' ? $t('studentWeb.public.school') : $t('studentWeb.public.private')}}</span>
+                <span class="tag-style" v-if="row.tag.source">{{ row.tag.source }}</span>
+                <span class="tag-style" v-if="row.tag.type">{{ row.tag.type }}</span>
+                <!-- <span class="tag-style">{{ row.tag.class }}</span> -->
+                <!-- <span class="tag-style">{{ row.tag.list }}</span> -->
+            </template>
+            <!-- <template slot-scope="{ row }" slot="score">
+                <span v-for="(item, index) in row.score" :key="index" style="margin-right: 10px;">{{ item }}</span>
+            </template> -->
+        </Table>
+    </div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+export default {
+    name: "",
+    components: {
+    },
+    data () {
+        return {
+            MyNo: "7",
+            MyName: this.$t('studentWeb.type.achievement'),
+            schoolRepCol: [
+                /* {
+                    width: 50,
+                    type: 'expand',
+                }, */
+                {
+                    title: this.$t("studentWeb.myAchievement.name"),
+                    // slot: "name",
+                    key: 'examName',
+                    align: "center"
+                    // tree: true,
+                    // width: 500,
+                },
+                /* {
+                    title: '创建人',
+                    key: 'creator',
+                    align: "center"
+                },
+                {
+                    title: '学科',
+                    key: 'class',
+                    align: "center"
+                }, */
+                {
+                    title: this.$t("studentWeb.myAchievement.score"),
+                    // slot: "score",
+                    key: "score",
+                    align: "center"
+                },
+                {
+                    title: this.$t("studentWeb.myAchievement.tag"),
+                    slot: "tag",
+                    width: 500,
+                    align: "center"
+                },
+                /* {
+                    title: '名单',
+                    key: 'list'
+                }, */
+                {
+                    title: this.$t("studentWeb.myAchievement.createTime"),
+                    key: 'time',
+                    align: "center"
+                }
+            ],
+            schoolRep: [],
+            showSchoolRep: [],
+            filterType: {
+                ownerType: "all",
+                sourceType: "all",
+            },
+            ownerType: "all",
+            sourceType: "all",
+            examType: "all",
+            ownerTypeList: [
+                {
+                    type: "all",
+                    name: this.$t('studentWeb.type.all')
+                },
+                {
+                    type: "school",
+                    name: this.$t('studentWeb.public.school')
+                },
+                {
+                    type: "teacher",
+                    name: this.$t('studentWeb.public.private')
+                },
+            ],
+            sourceTypeList: [
+                {
+                    type: "all",
+                    name: this.$t('studentWeb.type.all')
+                },
+                {
+                    type: "0",
+                    name: this.$t("studentWeb.exam.source.evMode1")
+                },
+                {
+                    type: "1",
+                    name: this.$t("studentWeb.exam.source.evMode2")
+                },
+                {
+                    type: "2",
+                    name: this.$t("studentWeb.exam.source.evMode3")
+                },
+            ],
+            examTypeList: [
+                {
+                    type: "all",
+                    name: this.$t('studentWeb.type.all')
+                },
+                {
+                    type: "normal",
+                    name: this.$t('totalAnalysis.ti_text8')
+                },
+                {
+                    type: "simulation",
+                    name: this.$t('totalAnalysis.ti_text7')
+                },
+                {
+                    type: "regular",
+                    name: this.$t('totalAnalysis.ti_text6')
+                },
+            ],
+            num: [],
+        }
+    },
+    created () {
+        this.$emit("onNavNo", this.MyNo);
+        this.$emit("onNavName", this.MyName);
+        this.$store.commit("ToggleSidebar", true);
+    },
+    mounted () {
+        /* this.showSchoolRep.forEach((item, index) => {
+            for (let i = index + 1; i < this.showSchoolRep.length; i++) {
+                if(item.id === this.showSchoolRep[i].id && !this.num.includes(index)) {
+                    this.num.push(i)
+                }
+            }
+        }); */
+        console.log(this.courseNow);
+        this.getReportList(this.courseNow)
+    },
+    methods: {
+        getReportList(classInfo) {
+            this.showSchoolRep = []
+            this.schoolRep = []
+            console.log(classInfo);
+            let cId = [classInfo.list]
+            let param = {
+                courseId: classInfo.id,
+                // code: classInfo.scope === "school" ? classInfo.school : classInfo.creatorId,
+                cId,
+                stuId: this.$store.state.userInfo.sub,
+            }
+            if(classInfo.subject.id) {
+                param.subjectId = classInfo.subject.id
+            }
+            this.$api.studentWeb.getClassScore(param).then(res => {
+                // 404表示没有评测记录
+                if(res.code === 404) {
+                    // this.showSchoolRep = []
+                } else if(res.info) {
+                    res.info.forEach(item => {
+                        item.tag = {
+                            source: item.source === '0' ? this.$t("studentWeb.exam.source.evMode1")
+                                    : (item.source === '1' ? this.$t("studentWeb.exam.source.evMode2")
+                                    : (item.source === '2' ? this.$t("studentWeb.exam.source.evMode3") : null)),
+                            type: (item.eType && item.eType.id) ? item.eType.name : null,
+                            owner: item.owner
+                        }
+                        item.total = 0
+                        // 学校评测才会存在多科,要匹配对应的科目
+                        if(item.owner === 'school') {
+                            let subIndex = item.subject.findIndex(sub => {
+                                return sub.id === classInfo.subject.id
+                            })
+                            if(subIndex != -1) {
+                                item.point[subIndex].forEach(point => {
+                                    item.total += point
+                                })
+                            }
+                        } else {
+                            // 个人评测只存在一张试卷
+                            item.point[0].forEach(point => {
+                                item.total += point
+                            })
+                        }
+                        item.total.toFixed(0)
+                        item.time = this.dateFormat(item.createTime)
+                        item.score = `${item.sum} / ${item.total}`
+                        this.schoolRep.push(item)
+                    })
+                    this.schoolRep.reverse()
+                    this.showSchoolRep = [...this.schoolRep]
+                }
+            })
+        },
+        //时间格式化处理
+        dateFormat(timestamp) {
+            var date = new Date(timestamp)
+            var Y = date.getFullYear() + '-'
+            var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-'
+            var D = (date.getDate() < 10 ? '0' + (date.getDate()) : date.getDate()) + ' '
+            var H = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ":"
+            var Min = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes())
+            var S = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()) + " "
+            return Y + M + D + H + Min;
+        },
+        handleSpan ({ row, column, rowIndex, columnIndex }) {
+            // 要把后面相同的使用[0, 0]隐藏掉
+            if(this.num.includes(rowIndex)) {
+                if(columnIndex != 2 && columnIndex != 3) {
+                    return [0, 0]
+                }
+            } else {
+                if(columnIndex != 2 && columnIndex != 3) {
+                    let x = row.mergeCol ? row.mergeCol : 1
+                    let y = 1
+                    return [x, y]
+                }
+            }
+        }
+    },
+    watch: {
+        filterType: {
+            deep: true,
+            handler(n, o) {
+                this.showSchoolRep = []
+                if(n.sourceType === '0') {
+                    this.showSchoolRep = this.schoolRep.filter(item => {
+                        return item.source === '0'
+                    })
+                } else if(n.sourceType === '1') {
+                    this.showSchoolRep = this.schoolRep.filter(item => {
+                        return item.source === '1'
+                    })
+                } else if(n.sourceType === '2') {
+                    this.showSchoolRep = this.schoolRep.filter(item => {
+                        return item.source === '2'
+                    })
+                } else {
+                    this.showSchoolRep = this.schoolRep
+                }
+
+                if(n.ownerType === "teacher") {
+                    this.showSchoolRep = this.showSchoolRep.filter(item => {
+                        return item.owner === "teacher"
+                    })
+                } else if(n.ownerType === "school") {
+                    this.showSchoolRep = this.showSchoolRep.filter(item => {
+                        return item.owner === "school"
+                    })
+                }
+            }
+        }
+    },
+    computed: {
+        ...mapGetters(["getNowCourse"]),
+        courseNow() {
+            return this.getNowCourse || JSON.parse(decodeURIComponent(localStorage.course, "utf-8"))
+        },
+    }
+}
+</script>
+
+<style lang="less" scoped>
+@import "./SchoolReport.less";
+</style>
+
+<style lang="less">
+@import "../WrongQusetion/iViewStyle.less";
+
+.achievement-report {
+    .ivu-tabs-tabpane td:nth-child(2) {
+        text-align: center !important;
+    }
+}
+</style>

+ 104 - 0
TEAMModelOS/ClientApp/src/components/student-web/common-style.less

@@ -30,4 +30,108 @@
         border-color: #6b6ba9;
         color: #6b6ba9;
     }
+
+    .layout-content-wrap {
+        height: 100%;
+        display: flex;
+
+        .layout-left-wrap {
+            width: 25%;
+            height: 100%;
+            padding-bottom: 10px;
+            box-shadow: 4px 1px 10px rgba(0, 0, 0, 0.1);
+            width: 25%;
+        }
+
+        .layout-right-wrap {
+            width: 75%;
+            height: 100%;
+            padding: 2% 3%;
+
+            .event-content {
+                height: 100%;
+            }
+        }
+
+    }
+
+
+    .event-view {
+        height: 100%;
+    }
+
+    .list-item-selected {
+        background: linear-gradient(-0.75turn, #fafafa, #d4ede1);
+        color: #03966a;
+        cursor: pointer;
+        width: 100%;
+    }
+}
+
+@media screen and (max-width: 1280px) {
+    .student-box {
+        .layout-content-wrap {
+
+            .layout-left-wrap {
+                width: 33%;
+            }
+
+            .layout-right-wrap {
+                width: 67%;
+            }
+        }
+    }
+}
+
+@media screen and (max-width: 1024px) {
+    .student-box {
+        .layout-content-wrap {
+
+            .layout-left-wrap {
+                width: 50%;
+            }
+
+            .layout-right-wrap {
+                width: 100%;
+            }
+        }
+    }
+}
+
+@media screen and (max-width: 768px) {
+    .student-box {
+        .layout-content-wrap {
+
+            .layout-left-wrap {
+                width: 100%;
+            }
+
+            .layout-right-wrap {
+                width: 100%;
+            }
+
+            .no-bar-content {
+                display: none;
+            }
+        }
+    }
+}
+
+@media screen and (max-width: 574px) {
+    .student-box {
+        .layout-content-wrap {
+
+            .layout-left-wrap {
+                width: 100%;
+            }
+
+            .layout-right-wrap {
+                width: 100%;
+            }
+
+            .no-bar-content {
+                display: none;
+            }
+        }
+    }
 }

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

@@ -1347,7 +1347,7 @@ export const routes = [{
         children: [{
                 name: "newhomeView",
                 path: "homeView",
-                component: resolve => require(['@/components/student-web/HomeView/HomeView'], resolve),
+                component: resolve => require(['@/components/student-web/HomeView/newHomeView'], resolve),
             },
             {
                 name: "courseList",
@@ -1379,6 +1379,7 @@ export const routes = [{
                 name: "achievement",
                 path: "achievement",
                 component: resolve => require(['@/components/student-web/achievement/MyAchievement'], resolve),
+                // component: resolve => require(['@/components/student-web/achievement/SchoolReport'], resolve),
             },
             {
                 name: "examView/evaluation",
@@ -1409,7 +1410,7 @@ export const routes = [{
                 // 自主学习
                 name: "studyView",
                 path: "studyView",
-                component: resolve => require(['@/components/student-web/StudyView/StudyView'], resolve),
+                component: resolve => require(['@/components/student-web/StudyView/StudyViews'], resolve),
             },
             {
                 name: "hiteachView",
@@ -1433,6 +1434,12 @@ export const routes = [{
                 name: "wrongQues",
                 path: "wrongQues",
                 component: resolve => require(['@/components/student-web/WrongQusetion/WrongQues'], resolve),
+            },
+            {
+                // 课堂记录
+                name: "classRecord",
+                path: "classRecord",
+                component: resolve => require(['@/components/student-web/ClassRecord/RecordView'], resolve),
             }
         ]
     },

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

@@ -32,9 +32,11 @@ const mutations = {
         console.log('刷新用户信息', JSON.stringify(obj))
         obj.schoolCode = obj.schoolCode || GLOBAL.DEFAULT_SCHOOL_CODE
         obj.hasSchool = obj.schoolCode !== GLOBAL.DEFAULT_SCHOOL_CODE
+        state.user.schoolCode = obj.schoolCode
         state.userInfo = obj
     },
     setSchoolCode(state, obj) {
+        state.user.schoolCode = obj || GLOBAL.DEFAULT_SCHOOL_CODE
         state.userInfo.schoolCode = obj || GLOBAL.DEFAULT_SCHOOL_CODE
         state.userInfo.hasSchool = obj !== GLOBAL.DEFAULT_SCHOOL_CODE
     },

+ 15 - 1
TEAMModelOS/ClientApp/src/store/module/studentWeb.js

@@ -90,6 +90,8 @@ export default {
         coureseMessageOpen: false, //是否打開加入課程的提示訊息
         choseDate: "",
         composeData: undefined,
+        nowCourse: undefined,
+        allCourse: [],
     },
 
     //定義方法
@@ -315,6 +317,12 @@ export default {
         setComposeData(state, data) {
             state.composeData = data
         },
+        setNowCourse(state, data) {
+            state.nowCourse = data
+        },
+        setAllCourse(state, data) {
+            state.allCourse = data
+        },
     },
     getters: {
         getStuUserInfo: (state) => {
@@ -445,6 +453,12 @@ export default {
         },
         getComposeData: (state) => {
             return state.composeData
-        }
+        },
+        getNowCourse(state) {
+            return state.nowCourse
+        },
+        getAllCourse(state) {
+            return state.allCourse
+        },
     },
 }

+ 1 - 1
TEAMModelOS/ClientApp/src/view/student-account/class/ClassMgt.vue

@@ -611,7 +611,7 @@ export default {
 
             } else {
                 this.students = this.allStudents.filter(item => {
-                    return item.classId == this.classListShow[this.curClassIndex]?.id
+                    return item.classId && item.classId == this.classListShow[this.curClassIndex]?.id
                 })
             }
         },

+ 2 - 2
TEAMModelOS/ClientApp/src/view/student-account/import/StuImport.vue

@@ -276,7 +276,6 @@ export default {
         },
         //检查是否新增班级
         checkUpdateClass(students) {
-            debugger
             let temp = {}
             for (let i = 0; i < students.length; i++) {
                 let classKey = `${students[i].classYear}${students[i].classNo}`
@@ -315,7 +314,8 @@ export default {
                 delete item.classroom
                 return item
             })
-            this.$api.stuAccount.ImportStudent(this.$store.state.user.schoolCode, temp).then(
+            let schoolCode = this.$store.state.userInfo.schoolCode
+            this.$api.stuAccount.ImportStudent(schoolCode, temp).then(
                 (res) => {
                     if (!res.error) {
                         this.$Message.info(this.$t('stuAccount.importOk'))

+ 6 - 0
TEAMModelOS/ClientApp/src/view/student-web/App.less

@@ -93,6 +93,10 @@
         }
     }
 
+    .selectClass {
+        margin-top: -2px;
+    }
+
     .profile-dropdown {
 
         #stuPhoto {
@@ -173,6 +177,8 @@
 
 .myContent {
     margin-top: 44px;
+    height: calc(100% - 45px);
+    width: 100%;
 }
 
 @media screen and (max-width: 1367px) {

+ 431 - 40
TEAMModelOS/ClientApp/src/view/student-web/AppNew.vue

@@ -8,45 +8,99 @@
                 </span>
                 <span :class="['mytitle', {'no-show-title': MyNo === '1'}]">{{ MyName }}</span>
             </div>
-            <div class="addClass" v-show="MyNo === '1'">
-                <!-- <div class="addClass" v-show="false"> -->
-                <Input v-special-char clearable v-model="addClassNo" :placeholder="$t('studentWeb.home.classPla')">
-                    <Button slot="append" @click="addClass">{{ $t('studentWeb.home.joinClass') }}</Button>
-                </Input>
+            <div :class="courseList.length ? 'selectClass' : 'addClass'">
+                <template v-if="courseList.length">
+                    <Select v-model="selectClass" style="width:250px" clearable filterable :placeholder="$t('cusMgt.sltCusTips')" @on-change="classChange">
+                        <Option v-for="(item, cIndex) in courseList" :value="cIndex + 1" :label="item.showName" :key="cIndex">
+                            <!-- 学校课程名称1(科目-名单) -->
+                            <span v-if="item.scope === 'school'">
+                                {{ item.name }}
+                                <span style="float: right;">
+                                    (
+                                    <span style="color: #76ae38;">{{ item.subject.name }}</span>
+                                    -
+                                    <span style="color: #6b6ba9;">{{ item.teacherName }}</span>
+                                    -
+                                    <span style="color: #8f8787;">{{ item.listName }}</span>
+                                    )
+                                </span>
+                            </span>
+                            <!-- 个人课程名称1(老师-名单1) -->
+                            <span v-else>
+                                {{ item.name }}
+                                <span style="float: right;">
+                                    (
+                                    <span style="color: #6b6ba9;">{{ item.teacherName }}</span>
+                                    -
+                                    <span style="color: #8f8787;">{{ item.listName }}</span>
+                                    )
+                                </span>
+                            </span>
+                        </Option>
+                    </Select>
+                    <!-- <Select v-model="selectClass" style="width:200px">
+                        <OptionGroup :label="`${course.name}${item.scope === 'school' ? ('-' + item.subject.name) : ''}`" v-for="(course, coIndex) in courseList" :key="coIndex">
+                            <Option v-for="(item, indexx) in course.roster" :value="indexx" :key="indexx">{{ item.listName }}</Option>
+                        </OptionGroup>
+                    </Select> -->
+                    <Icon v-show="selectClass" type="md-information-circle" color="#9e9e9e" size="18" :title="$t('jyzx.offline.info')" @click="showInfo = true" />
+                    <!-- <Icon type="md-add-circle" color="#02B35A" size="17" title="加入课程" @click="addCourse = true" /> -->
+                </template>
+                <template v-else>
+                     <Input v-special-char clearable v-model="addClassNo" :placeholder="$t('studentWeb.home.classPla')">
+                        <Button slot="append" @click="addClass">{{ $t('studentWeb.home.joinClass') }}</Button>
+                    </Input>
+                </template>
             </div>
             <div style="display: flex;">
                 <Menu mode="horizontal" :active-name="MyNo" class="menubar" v-if="windowWidth > 851">
-                    <MenuItem name="1" to="/studentWeb/homeView" :title="$t('studentWeb.type.home')">
-                        <svg-icon icon-class="home" class="tabIcon2" />
-                        <span class="no-show" v-show="MyNo != 1">{{ $t('studentWeb.type.home') }}</span>
-                    </MenuItem>
-                    <MenuItem name="2" to="/studentWeb/courseList" :title="$t('studentWeb.courseListTitle')">
+                    <!-- 课堂互动 -->
+                    <!-- <MenuItem name="4" :to="getSrvAdr" target="_blank" :title="$t('studentWeb.type.classInteraction')">
+                        <Icon custom="iconfont icon-ketanghudonghangwei" size="18" style="font-weight: bold" />
+                        <span class="no-show" v-show="MyNo != 4">{{ $t('studentWeb.type.classInteraction') }}</span>
+                    </MenuItem> -->
+                    <!-- <MenuItem name="2" to="/studentWeb/courseList" :title="$t('studentWeb.courseListTitle')">
                         <svg-icon icon-class="course" class="tabIcon1" />
                         <span class="no-show" v-show="MyNo != 2">{{ $t('studentWeb.course') }}</span>
+                    </MenuItem> -->
+                    <!-- 课堂记录 -->
+                    <MenuItem name="10" to="/studentWeb/classRecord" :title="$t('studentWeb.courseContent.classRecord')" v-show="selectClass">
+                        <svg-icon icon-class="course" class="tabIcon1" />
+                        <span class="no-show" v-show="MyNo != 10">{{ $t('studentWeb.courseContent.classRecord') }}</span>
                     </MenuItem>
-                    <MenuItem name="5" to="/studentWeb/examView" :title="$t('studentWeb.type.exam')">
+                    <!-- 评测 -->
+                    <MenuItem name="5" to="/studentWeb/examView" :title="$t('studentWeb.type.exam')" v-show="selectClass">
                         <svg-icon icon-class="test" class="tabIcon3" />
                         <span class="no-show" v-show="MyNo != 5">{{ $t('studentWeb.type.exam') }}</span>
                     </MenuItem>
-                    <MenuItem name="6" to="/studentWeb/homeworkView" :title="$t('studentWeb.type.homework')">
+                    <!-- 作业 -->
+                    <MenuItem name="6" to="/studentWeb/homeworkView" :title="$t('studentWeb.type.homework')" v-show="selectClass">
                         <svg-icon icon-class="doc" class="tabIcon3" />
                         <span class="no-show" v-show="MyNo != 6">{{ $t('studentWeb.type.homework') }}</span>
                     </MenuItem>
+                    <!-- <MenuItem name="9" to="/studentWeb/studyView" :title="$t('studentWeb.type.studyview')">
+                        <svg-icon icon-class="note" class="tabIcon2" />
+                        <span class="no-show" v-show="MyNo != 9">{{ $t('studentWeb.type.studyview') }}</span>
+                    </MenuItem> -->
+                    <!-- 活动 -->
                     <MenuItem name="3" to="/studentWeb/eventView" :title="$t('studentWeb.type.activity')">
                         <svg-icon icon-class="selflearning" class="tabIcon4" />
                         <span class="no-show" v-show="MyNo != 3">{{ $t('studentWeb.type.activity') }}</span>
                     </MenuItem>
-                    <MenuItem name="7" to="/studentWeb/achievement" :title="$t('studentWeb.type.achievement')">
-                        <Icon custom="iconfont icon-chengjitongji" size="18" style="font-weight: bold" />
-                        <span class="no-show" v-show="MyNo != 7">{{ $t('studentWeb.type.achievement') }}</span>
-                    </MenuItem>
+                    <!-- 错题本 -->
                     <!-- <MenuItem name="8" to="/studentWeb/wrongQues" :title="$t('studentWeb.type.wrongTopic')">
                         <Icon custom="iconfont icon-cuotiji" size="17" class="tabIcon1" />
                         <span class="no-show" v-show="MyNo != 8">{{ $t('studentWeb.type.wrongTopic') }}</span>
                     </MenuItem> -->
-                    <MenuItem name="4" :to="getSrvAdr" target="_blank" :title="$t('studentWeb.type.classInteraction')">
-                        <Icon custom="iconfont icon-ketanghudonghangwei" size="18" style="font-weight: bold" />
-                        <span class="no-show" v-show="MyNo != 4">{{ $t('studentWeb.type.classInteraction') }}</span>
+                    <!-- 成绩 -->
+                    <MenuItem name="7" to="/studentWeb/achievement" :title="$t('studentWeb.type.achievement')" v-show="selectClass">
+                        <Icon custom="iconfont icon-chengjitongji" size="18" style="font-weight: bold" />
+                        <span class="no-show" v-show="MyNo != 7">{{ $t('studentWeb.type.achievement') }}</span>
+                    </MenuItem>
+                    <!-- 首页 -->
+                    <MenuItem name="1" to="/studentWeb/homeView" :title="$t('studentWeb.type.home')">
+                        <svg-icon icon-class="home" class="tabIcon2" />
+                        <span class="no-show" v-show="MyNo != 1">{{ $t('studentWeb.type.home') }}</span>
                     </MenuItem>
                 </Menu>
                 <!-- 头像 -->
@@ -63,22 +117,6 @@
                                 <svg-icon icon-class="home" class="profile-pop-icon profile-pop-icon-1" />
                                 {{ $t('studentWeb.type.home') }}
                             </div>
-                            <div class="profile-pop-item" @click="goto('/studentWeb/courseList')">
-                                <svg-icon icon-class="course" class="profile-pop-icon profile-pop-icon-1" />
-                                {{ $t('studentWeb.course') }}
-                            </div>
-                            <div class="profile-pop-item" @click="goto('/studentWeb/examView')">
-                                <svg-icon icon-class="test" style="margin-left: 2px; margin-right: -2px;" class="profile-pop-icon profile-pop-icon-1" />
-                                {{ $t('studentWeb.type.exam') }}
-                            </div>
-                            <div class="profile-pop-item" @click="goto('/studentWeb/homeworkView')">
-                                <svg-icon icon-class="doc" class="profile-pop-icon profile-pop-icon-1" />
-                                {{ $t('studentWeb.type.homework') }}
-                            </div>
-                            <div class="profile-pop-item" @click="goto('/studentWeb/eventView')">
-                                <svg-icon icon-class="selflearning" style="margin-left: 3px; margin-right: -3px;" class="profile-pop-icon profile-pop-icon-1" />
-                                {{ $t('studentWeb.type.activity') }}
-                            </div>
                             <div class="profile-pop-item" @click="goto('/studentWeb/achievement')">
                                 <Icon custom="iconfont icon-chengjitongji" size="16" class="profile-pop-icon" style="font-weight: bold;" />
                                 {{ $t('studentWeb.type.achievement') }}
@@ -87,11 +125,31 @@
                                 <Icon custom="iconfont icon-cuotiji" size="16" class="profile-pop-icon" />
                                 {{ $t('studentWeb.type.wrongTopic') }}
                             </div> -->
-                            <div class="profile-pop-item" @click="goto(getSrvAdr, true)">
-                                <Icon custom="iconfont icon-ketanghudonghangwei" size="16" class="profile-pop-icon" style="font-weight: bold;" />
-                                {{ $t('studentWeb.type.classInteraction') }}
+                            <div class="profile-pop-item" @click="goto('/studentWeb/eventView')">
+                                <svg-icon icon-class="selflearning" style="margin-left: 3px; margin-right: -3px;" class="profile-pop-icon profile-pop-icon-1" />
+                                {{ $t('studentWeb.type.activity') }}
+                            </div>
+                            <!-- <div class="profile-pop-item" @click="goto('/studentWeb/courseList')">
+                                <svg-icon icon-class="course" class="profile-pop-icon profile-pop-icon-1" />
+                                {{ $t('studentWeb.course') }}
+                            </div> -->
+                            <div class="profile-pop-item" @click="goto('/studentWeb/classRecord')" v-show="selectClass">
+                                <svg-icon icon-class="course" style="margin-left: 2px; margin-right: -2px;" class="profile-pop-icon profile-pop-icon-1" />
+                                {{ $t('studentWeb.courseContent.classRecord') }}
+                            </div>
+                            <div class="profile-pop-item" @click="goto('/studentWeb/examView')" v-show="selectClass">
+                                <svg-icon icon-class="test" style="margin-left: 2px; margin-right: -2px;" class="profile-pop-icon profile-pop-icon-1" />
+                                {{ $t('studentWeb.type.exam') }}
+                            </div>
+                            <div class="profile-pop-item" @click="goto('/studentWeb/homeworkView')" v-show="selectClass">
+                                <svg-icon icon-class="doc" class="profile-pop-icon profile-pop-icon-1" />
+                                {{ $t('studentWeb.type.homework') }}
                             </div>
                         </template>
+                        <div class="profile-pop-item" @click="goto(getSrvAdr, true)">
+                            <Icon custom="iconfont icon-ketanghudonghangwei" size="16" class="profile-pop-icon" style="font-weight: bold;" />
+                            {{ $t('studentWeb.type.classInteraction') }}
+                        </div>
                         <div class="profile-pop-item" @click="onSet">
                             <svg-icon icon-class="setting" class="profile-pop-icon profile-pop-icon-2" />
                             {{ $t("studentWeb.home.setting") }}
@@ -109,12 +167,63 @@
             <router-view @onNavNo="getNavNo" @onNavName="getNavName" @onMessage="getmessage" v-if="isRouterAlive">
             </router-view>
         </div>
+        <!-- 详细信息 -->
+        <Modal v-model="showInfo" :title="$t('lessonRecord.lessonInfo')" mask-closable :width="700">
+            <div v-if="courseList.length && selectClass">
+                <p style="margin-bottom: 20px; font-weight: bold;">{{ $t("studentWeb.courseContent.classID") }}:{{ courseList[selectClass - 1].no }}</p>
+
+                <p style="margin-bottom: 20px; font-weight: bold;">{{ $t("studentWeb.baseInfo.subjectName") }}:{{ courseList[selectClass - 1].name }}</p>
+
+                <p style="margin-bottom: 20px; font-weight: bold;">{{ $t("studentWeb.baseInfo.stuList") }}:{{ courseList[selectClass - 1].listName }}</p>
+
+                <p style="margin-bottom: 20px; font-weight: bold;">{{ $t("studentWeb.courseContent.teacher") }}:{{ courseList[selectClass - 1].teacherName }}</p>
+
+                <p style="margin-bottom: 20px; font-weight: bold;">{{ $t("studentWeb.courseContent.classTime") }}:
+                    <span v-if="!courseList[selectClass - 1].roster.time.length">{{ $t("studentWeb.courseContent.noTime") }}</span>
+                    <template v-else>
+                        <span v-for="(time, tIndex) in courseList[selectClass - 1].roster.time" :key="tIndex" style="margin-right: 10px;">{{ time.classTime }}</span>
+                    </template>
+                </p>
+
+                <p style="margin-bottom: 20px; font-weight: bold;">
+                    {{ $t("studentWeb.courseContent.classroom") }}:{{ courseList[selectClass - 1].roster.roomName ? courseList[selectClass - 1].roster.roomName : $t("studentWeb.courseContent.noRoom") }}
+                </p>
+
+                <p style="margin-bottom: 20px; font-weight: bold;">{{ $t("studentWeb.courseContent.addedTime") }}:{{ courseList[selectClass - 1].courseAddDate }}</p>
+            </div>
+            
+            <div v-if="studentList.data.length">
+                <Table :columns="stuCol" :data="studentList.data" :height="300" v-if="studentList.type === 'class'">
+                    <template slot-scope="{ row }" slot="groupName">
+                        <span>
+                            {{ row.groupName ? row.groupName : '--'}}
+                        </span>
+                    </template>
+                </Table>
+                <Table :columns="stuColTeach" :data="studentList.data" :height="300" v-if="studentList.type === 'teach'">
+                    <template slot-scope="{ row }" slot="nickname">
+                        <span>
+                            {{ row.nickname ? row.nickname : '--'}}
+                        </span>
+                    </template>
+                </Table>
+            </div>
+            <div slot="footer"></div>
+        </Modal>
+        <!-- 添加课程 -->
+        <Modal v-model="addCourse" title="添加课程" mask-closable>
+            <Input v-special-char clearable v-model="addClassNo" :placeholder="$t('studentWeb.home.classPla')">
+                <Button slot="append" @click="addClass">{{ $t('studentWeb.home.joinClass') }}</Button>
+            </Input>
+            <div slot="footer"></div>
+        </Modal>
     </div>
 </template>
 
 <script>
 import jwtDecode from 'jwt-decode';
 import PersonalPhoto from '@/components/public/personalPhoto/Index.vue';
+import { mapGetters } from 'vuex';
 export default {
     name: "App",
     components: {
@@ -141,6 +250,87 @@ export default {
             userInfo: {},
             isAddClass: false,
             addClassNo: '',
+            selectClass: null,
+            courseList: [],
+            studentList: {
+                type: null,
+                data: [],
+            },
+            showInfo: false,
+            addCourse: false,
+            timeTable: undefined,
+            week: [
+                {
+                    name: "MON",
+                    cn: this.$t("studentWeb.week.mon")
+                }, {
+                    name: "TUE",
+                    cn: this.$t("studentWeb.week.tue")
+                }, {
+                    name: "WED",
+                    cn: this.$t("studentWeb.week.wed")
+                }, {
+                    name: "THU",
+                    cn: this.$t("studentWeb.week.thu")
+                }, {
+                    name: "FRI",
+                    cn: this.$t("studentWeb.week.fri")
+                }
+            ],
+            stuCol: [
+                {
+                    title: this.$t("studentWeb.courseContent.seatNo"),
+                    key: "no",
+                },
+                {
+                    title: this.$t("studentWeb.courseContent.stuNum"),
+                    key: "id",
+                },
+                {
+                    title: this.$t("studentWeb.courseContent.name"),
+                    key: "name",
+                },
+                /* {
+                    title: this.$t("studentWeb.courseContent.name"),
+                    key: "nickname",
+                }, */
+                {
+                    title: this.$t("studentWeb.courseContent.accountType"),
+                    key: "typeName",
+                },
+                {
+                    title: this.$t("studentWeb.courseContent.group"),
+                    slot: "groupName",
+                }
+            ],
+            stuColTeach: [
+                /* {
+                    title: this.$t("studentWeb.courseContent.seatNo"),
+                    key: "no",
+                }, */
+                {
+                    title: this.$t("studentWeb.courseContent.stuNum"),
+                    key: "id",
+                },
+                {
+                    title: this.$t("studentWeb.courseContent.name"),
+                    key: "name",
+                },
+                {
+                    title: this.$t("studentWeb.courseContent.nickName"),
+                    slot: "nickname",
+                },
+                {
+                    title: this.$t("studentWeb.courseContent.accountType"),
+                    key: "typeName",
+                },
+            ],
+            // 取消课程后不需要跳转的路由
+            noJumpRouter: [
+                "/studentWeb/homeView",
+                "/studentWeb/eventView",
+                "/studentWeb/wrongQues"
+            ]
         };
     },
     computed: {
@@ -178,6 +368,7 @@ export default {
                 return ""
             }
         },
+        ...mapGetters(["getNowCourse"])
     },
     watch: {
         courseID: function (value) {
@@ -191,12 +382,25 @@ export default {
     created() {
         this.getUsers();
         this.$store.dispatch('user/checkStudentProfile');// 檢查學生的詳細資訊,刷新后同步localStorage数据
+        this.selectClass = Number(localStorage.getItem("courseIndex"))
     },
     mounted() {
         this.getStudentData()
+        this.findSchoolInfo()
+        this.getClassName()
+        // this.getClassList()
         this.$nextTick(() => {
             window.addEventListener("resize", this.onResize);
         });
+        // let index = localStorage.getItem("course")
+        // console.log(index);
+        // this.classChange(index)
+        
+        this.$EventBus.$off('classIndex')
+        this.$EventBus.$on('classIndex', index => {
+            this.selectClass = index
+            this.classChange(index)
+        })
     },
     beforeDestroy() {
         window.removeEventListener("resize", this.onResize);
@@ -257,10 +461,14 @@ export default {
         onQuit() {
             this.$store.commit('user/resetSchoolProfile')
             this.$store.commit("ChangeItemName", null)
+            this.$store.commit("setNowCourse", undefined)
+            this.$store.commit("setAllCourse", [])
             localStorage.removeItem('Item')
             localStorage.removeItem('subjectNow')
             localStorage.removeItem('examInfo')
             localStorage.removeItem('paperInfo')
+            localStorage.removeItem('course')
+            localStorage.removeItem('courseIndex')
             this.$User.logout()
             this.$router.push({
                 path: '/login'
@@ -278,6 +486,7 @@ export default {
         // 加入课程
         addClass() {
             if (this.addClassNo) {
+                let courseIndex = this.selectClass
                 let isStu = this.userInfo.scope != "tmduser"
                 let req = {
                     stuListNo: this.addClassNo,
@@ -294,8 +503,13 @@ export default {
                     if (res.status == 0) {
                         this.$Message.success(this.$t('studentWeb.courseType.success'))
                         this.addClassNo = ""
-                        // 加入成功后,刷新首页
-                        this.reload()
+                        this.addCourse = false
+                        this.courseList = []
+                        this.getClassName()
+                        if(this.noJumpRouter.includes(this.$route.path)) {
+                            // 加入成功后,刷新首页
+                            this.reload()
+                        }
                     } else if (res.status == 2) {
                         this.$Message.warning(this.$t('studentWeb.courseType.warning'))
                     } else if (res.status == -1) {
@@ -315,6 +529,183 @@ export default {
                 this.$router.push(path)
             }
         },
+        getClassList(groups) {
+            let param = {
+                userid: this.userInfo.sub,
+                school: this.userInfo.azp
+            }
+            param.userType = this.userInfo.scope === "tmduser" ? "tmdid" : "schoolid"
+            this.$api.studentWeb.getClassList(param).then(res => {
+                if(res.courses.length) {
+                    var schclassIds = []
+                    res.courses.forEach(item => {
+                        if(item.course) {
+                            let courseAddDate = this.dateFormat(item.stuCourse.createTime)
+                            // scope = school:学校课程,scope = private:老师课程
+                            // 把classId、stulist合并,可以一起请求/grouplist/get-members-listids,会全部返回
+                            let allClassId = item.stuCourse.classId.concat(item.stuCourse.stulist)
+                            schclassIds = schclassIds.concat(allClassId)
+                            // let haveCour = 
+                            item.course.schedule.forEach((sch, sIn) => {
+                                let haveClassId = sch.classId || sch.stulist
+                                let listName = groups.find(group => {
+                                    return group.id === haveClassId
+                                })
+                                sch.time.map(schTime => {
+                                    schTime.classTime = this.$t("studentWeb.courseContent.noTime")
+                                    this.week.map(item => {
+                                        if(item.name == schTime.week) {
+                                            schTime.classTime = item.cn
+                                        }
+                                    })
+                                    this.timeTable.forEach(item => {
+                                        if(schTime.id == item.id && schTime.id) {
+                                            schTime.classTime = schTime.classTime + " " + item.time + " (" + item.label + ")"
+                                        }
+                                    })
+                                })
+                                sch.listName = listName ? listName.name : ""
+                                if(haveClassId && (allClassId.length && allClassId.includes(haveClassId))) {
+                                    this.courseList.push({
+                                        id: item.course.id,
+                                        no: item.course.no,
+                                        name: item.course.name,
+                                        subject: item.course.subject,
+                                        scope: item.course.scope,
+                                        school: item.course.school,
+                                        creatorId: item.course.creatorId,
+                                        desc: item.course.desc,
+                                        roster: sch,
+                                        teacherName: sch.teacherName,
+                                        list: listName ? listName.id : "",
+                                        listName: listName ? listName.name : "",
+                                        showName: `${item.course.name}(${sch.teacherName}-${listName ? listName.name : ""})`,
+                                        courseAddDate
+                                    })
+                                }
+                            })
+                        }
+                    })
+                    if(this.selectClass && this.selectClass <= this.courseList.length) {
+                        this.classChange(this.selectClass)
+                    } else {
+                        this.selectClass = 0
+                    }
+                    this.$store.commit("setAllCourse", this.courseList)
+                }
+            })
+        },
+        getClassName(ids) {
+            let params = {
+                ids,
+                schoolId: this.userInfo.azp,
+            }
+            this.$api.studentWeb.getAllGrouplist({}).then(res => {
+                if(res.groups) {
+                    this.getClassList(res.groups)
+                }
+            }).catch(e => {
+                console.log(e);
+            })
+        },
+        getNameByHome() {
+            this.courseList = []
+            this.getClassName()
+            if(this.noJumpRouter.includes(this.$route.path)) {
+                // 加入成功后,刷新首页
+                this.reload()
+            }
+        },
+
+        // 查找班级
+        findSchoolInfo() {
+            let params = {}
+            // 醍摩豆登陆——> roles有teacher
+            if (this.userInfo.scope === "tmduser") {
+                params = {userType: "tmdid"}
+            }
+            // 学生账号登陆
+            else {
+                params = {userType: "schoolid"}
+            }
+            this.$api.studentWeb.getSchoolInfo(params).then(res => {
+                if(res.status == 200) {
+                    let period = JSON.parse(decodeURIComponent(localStorage.student_profile, "utf-8")).classinfo ? JSON.parse(decodeURIComponent(localStorage.student_profile, "utf-8")).classinfo.periodId : null
+                    this.timeTable = res.school_base.period.find(periods => {
+                        return periods.id === period
+                    }).timetable
+                }
+            })
+        },
+        // 查找学生信息(标准)
+        findStuInfor(course) {
+            // this.stuGroup = []
+            // this.stuList = []
+            let req = {
+                ids: [course.list],
+                schoolId: course.school
+            }
+            this.$api.common.getGroupListByIds(req).then(res => {
+                if(res.groups.length) {
+                    this.studentList.type = res.groups[0].type
+                }
+                if(res.members.length) {
+                    let arr = this._.cloneDeep(res.members)
+                    // type表示角色类型,1:醍摩豆登陆,2:学生登陆
+                    arr.forEach((item) => {
+                        if(item.id === this.$store.state.userInfo.sub) {
+                            item.name = `${item.name}(${this.$t("studentWeb.courseContent.me")})`
+                        }
+                        if(item.type === 2) {
+                            item.typeName = this.$t("studentWeb.courseContent.stuAccount")
+                        } else if(item.type === 1) {
+                            item.typeName = this.$t("studentWeb.courseContent.tmdNum")
+                        }
+                        this.studentList.data.push(item)
+                    })
+                }
+            }).finally(() => {
+                // this.isLoad = false
+            })
+        },
+        dateFormat(timestamp) {
+            var date = new Date(timestamp)
+            var Y = date.getFullYear() + '-'
+            var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-'
+            var D = (date.getDate() < 10 ? '0' + (date.getDate()) : date.getDate()) + ' '
+            var H = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ":"
+            var Min = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes())
+            var S = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()) + " "
+            return Y + M + D + H + Min;
+        },
+        classChange(value) {
+            if(value) {
+                this.findStuInfor(this.courseList[value - 1])
+                if(this.getNowCourse) {
+                    this.reload()
+                } else {
+                    // let path = localStorage.getItem("target_path")
+                    if(this.noJumpRouter.includes(this.$route.path)) {
+                        this.$router.push({
+                            path: '/studentWeb/classRecord'
+                        })
+                    }
+                    
+                }
+                this.$store.commit("setNowCourse", this.courseList[value - 1])
+                localStorage.setItem("course", encodeURIComponent(JSON.stringify(this.courseList[value - 1])))
+                localStorage.setItem("courseIndex", value)
+            } else {
+                this.$store.commit("setNowCourse", undefined)
+                localStorage.removeItem('course')
+                localStorage.removeItem('courseIndex')
+                if(!this.noJumpRouter.includes(this.$route.path)) {
+                    this.$router.push({
+                        path: '/studentWeb/homeView'
+                    })
+                }
+            }
+        },
     },
 };
 </script>

+ 39 - 5
TEAMModelOS/ClientApp/src/view/student-web/AppiView.less

@@ -38,16 +38,50 @@
         margin-right: 20px;
     }
 
-    .addClass {
-        .ivu-input-icon {
-            line-height: 30px;
-            right: 90px;
-        }
+    .selectClass {
 
         .ivu-input,
         .ivu-btn {
             height: 28px;
         }
+
+        .ivu-icon {
+            margin-left: 5px;
+            cursor: pointer;
+        }
+
+        .ivu-select-selection {
+            border-radius: 15px;
+            background-color: #b4d4bb;
+            border-color: #b4d4bb;
+        }
+
+        .ivu-select-input {
+            // color: #fff;
+            // 修改 placeholder 的颜色
+            &::-webkit-input-placeholder{
+                color:#515a6e;
+            }
+            &::-moz-placeholder{   /* Mozilla Firefox 19+ */
+                color:#515a6e;
+            }
+            &::-moz-placeholder{    /* Mozilla Firefox 4 to 18 */
+                color:#515a6e;
+            }
+            &::-ms-input-placeholder{  /* Internet Explorer 10-11 */
+                color:#515a6e;
+            }
+        }
+    }
+
+}
+
+.ivu-modal,
+.addClass {
+    .ivu-input-icon {
+        line-height: 30px;
+        right: 90px;
+        cursor: pointer;
     }
 }