Browse Source

Merge branch 'liqk/develop' into develop-rc

liqk 3 years ago
parent
commit
b09a2ad039
21 changed files with 2032 additions and 79 deletions
  1. 17 8
      TEAMModelBI/ClientApp/src/view/index/index.vue
  2. 2 0
      TEAMModelOS.SDK/Models/Cosmos/Common/GroupList.cs
  3. 20 19
      TEAMModelOS/ClientApp/public/lang/en-US.js
  4. 15 14
      TEAMModelOS/ClientApp/public/lang/zh-CN.js
  5. 15 17
      TEAMModelOS/ClientApp/public/lang/zh-TW.js
  6. 1 1
      TEAMModelOS/ClientApp/src/components/coursemgt/StudentList.vue
  7. 165 0
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/ChartHome/ClassPoint.vue
  8. 270 0
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/ChartHome/ExamPerform.vue
  9. 263 0
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/ChartHome/HomeworkPoint.vue
  10. 97 0
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeViewnnnnew.less
  11. 509 0
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeViewnnnnew.vue
  12. BIN
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/noData.png
  13. 51 11
      TEAMModelOS/ClientApp/src/utils/js-fn.js
  14. 42 6
      TEAMModelOS/ClientApp/src/view/learnactivity/CreatePrivEva.vue
  15. 1 1
      TEAMModelOS/ClientApp/src/view/student-account/class/ClassMgt.vue
  16. 1 1
      TEAMModelOS/ClientApp/src/view/student-account/stuMgt/ImportStudent.vue
  17. 1 1
      TEAMModelOS/ClientApp/src/view/student-account/stuMgt/StuMgt.vue
  18. 178 0
      TEAMModelOS/ClientApp/src/view/student-web/App.less
  19. 327 0
      TEAMModelOS/ClientApp/src/view/student-web/AppNew.vue
  20. 55 0
      TEAMModelOS/ClientApp/src/view/student-web/AppiView.less
  21. 2 0
      TEAMModelOS/Controllers/Both/GroupListController.cs

+ 17 - 8
TEAMModelBI/ClientApp/src/view/index/index.vue

@@ -168,7 +168,8 @@
                                 </svg>
                             </div>
                             </p>
-                            <div class="commonbox-versions">
+                            <div class="commonbox-versions" v-loading="loading.versions"
+                                element-loading-background="rgba(0, 0, 0, 0.2)">
                                 <div class="commonbox-versions-title">
                                     <p class="versions-title-name">基础版</p>
                                     <p class="versions-title-num">数量:
@@ -180,7 +181,8 @@
                                 </div>
 
                             </div>
-                            <div class="commonbox-versions">
+                            <div class="commonbox-versions" v-loading="loading.versions"
+                                element-loading-background="rgba(0, 0, 0, 0.2)">
                                 <div class="commonbox-versions-title">
                                     <p class="versions-title-name">标准版</p>
                                     <p class="versions-title-num">数量:
@@ -192,7 +194,8 @@
                                 </div>
 
                             </div>
-                            <div class="commonbox-versions">
+                            <div class="commonbox-versions" v-loading="loading.versions"
+                                element-loading-background="rgba(0, 0, 0, 0.2)">
                                 <div class="commonbox-versions-title">
                                     <p class="versions-title-name">专业版</p>
                                     <p class="versions-title-num">数量:
@@ -215,7 +218,8 @@
                             </svg>
                         </div>
                         </p>
-                        <div class="bottom-rightbox-right">
+                        <div class="bottom-rightbox-right" v-loading="loading.sizeType"
+                            element-loading-background="rgba(0, 0, 0, 0.2)">
                             <Size :lineData="totalArea.sizePie" :sizenum="allSize"></Size>
                         </div>
                     </div>
@@ -331,9 +335,11 @@ export default {
         let loading = ref({
             basics: true,
             basics2: true,
-            lessonData: true,
-            lessonAndactivity: true,
+            // lessonData: true,
+            // lessonAndactivity: true,
             active: true,
+            versions: true,
+            sizeType: true,
         })
         let onlineModels = ref('all')
         let allSize = ref({
@@ -1220,6 +1226,7 @@ export default {
                             let nums = parseInt(i) + 1
                             replaceTime[i].value == onlineData[onlineData.length - 1].key ? replaceTime.splice(nums) : ''
                         }
+                        console.log(onlineData, '查看内容')
                         //在线人数趋势
                         onlineData.forEach((x) => {
                             for (let s in replaceTime) {
@@ -1235,13 +1242,13 @@ export default {
                         //处理在线人员区分(学生)
                         onlineStudent.forEach((u) => {
                             for (let s in replaceTime) {
-                                replaceTime[s].value === u.key ? (replaceTime[s].num = u.value) : ''
+                                replaceTime[s].value === u.key ? (replaceTime[s].student = u.value) : ''
                             }
                         })
                         //处理在线人员区分(醍摩豆学生)
                         onlineTmdstudent.forEach((t) => {
                             for (let s in replaceTime) {
-                                replaceTime[s].value === t.key ? (replaceTime[s].num = t.value) : ''
+                                replaceTime[s].value === t.key ? (replaceTime[s].tmdStudent = t.value) : ''
                             }
                         })
                         replaceTime.forEach((e) => {
@@ -1581,6 +1588,7 @@ export default {
                     totalArea.value.pie1 = dataBasics
                     totalArea.value.pie2 = dataStandard
                     totalArea.value.pie3 = dataMajor
+                    loading.value.versions = false
                 }
             }).catch((error) => {
                 ElMessage.error('各版本获取异常')
@@ -1639,6 +1647,7 @@ export default {
                 })
                 console.log(dataArr, '饼图数据统计')
                 totalArea.value.sizePie.series[0].data = dataArr.various
+                loading.value.sizeType = false
                 // let ss = proxy.$common.convertSize(res.typeStics.video)
                 // console.log(ss, '大小')
             })

+ 2 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/GroupList.cs

@@ -266,6 +266,8 @@ namespace TEAMModelOS.SDK.Models
         public string scope { get; set; }
         public string subject { get; set; }
         public string period { get; set; }
+        public string subjectId { get; set; }
+        public string periodId { get; set; }
         public string name { get; set; }
         public string id { get; set; }
         public List<GroupListGrp> groups { get; set; } = new List<GroupListGrp>();

+ 20 - 19
TEAMModelOS/ClientApp/public/lang/en-US.js

@@ -608,7 +608,6 @@ const LANG_EN_US = {
     },
     // 课程管理
     cusMgt: {
-        // ManageCourse.vue
         searchHolder: 'Search',
         delBatch: 'Batch delete',
         delCus: 'Delete Course',
@@ -3728,6 +3727,16 @@ const LANG_EN_US = {
             vote: 'Poll',
             survey: 'Survey',
             homework: 'Homework',
+            title: {
+                classRecord: "老師發佈的課堂記錄",
+                activity: "老師發佈的活動",
+                notice1: "班級公告",
+                notice2: "課程公告",
+                exam: "評測成績分析",
+                homework: "作業評分",
+                classScore: "課例記分",
+            },
+            toLook: "現在去看",
         },
         public: {
             noData: 'No data yet',
@@ -3750,6 +3759,7 @@ const LANG_EN_US = {
             hour: "H",
             minute: "M",
             mustFile: "Must Upload",
+            uploadTime: "上傳時間",
         },
         type: {
             home: "Home",
@@ -4543,6 +4553,9 @@ const LANG_EN_US = {
             wrongNum: "No. of Incorrect",
         },
         myAchievement: {
+            examAch: "評量成績",
+            hwAch: "作業成績",
+            cusAch: "老師給分",
             examMode: "Assessment Mode",
             examIn: "Source",
             name: "Name",
@@ -5117,8 +5130,8 @@ const LANG_EN_US = {
         props6: 'File uploaded successfully!',
         props7: 'Not enough storage space!',
         uploadText: 'Tap or drag to upload',
-
         resTips: 'HiTeach generates teaching materials that only support HTEX format previews',
+        space: '可用空間:',
         calcing: 'Calculating...',
         blobFull: '(Full)',
         otherType: 'Other types',
@@ -5229,19 +5242,18 @@ const LANG_EN_US = {
         },
         authority: {
             'classroom': 'Classroom Settings',
-            'system': 'School Basic Data Management',
-            'studentAccount': 'Student Account Management',
-            'teachermgmt': 'Teacher Account Management',
             'classroom-read': 'View Classroom Information',
             'classroom-upd': 'Change Classroom Settings',
+            'schoolSetting': 'School Basic Data Management',
             'schoolSetting-read': 'View School Basic Settings',
             'schoolSetting-upd': 'Change School Basic Settings',
+            'student': 'Student Account Management',
             'student-read': 'View Student Account',
             'student-upd': 'Change Student Account',
-            'teacher-checkTeacher': 'Check if the teacher can view',
+            'teacher': 'Teacher Account Management',
             'teacher-read': 'View Teacher Account',
             'teacher-upd': 'Change Teacher Account',
-            'manageCourse': ' Course Setting Management',
+            'course': ' Course Setting Management',
             'course-read': 'View Course Setting Information',
             'course-upd': 'Modify Course Setting Information',
             'newCoursePlan': 'Course Scheduling Management',
@@ -5433,6 +5445,7 @@ const LANG_EN_US = {
         importTips7: '5. note: Note about the teacher, optional',
         importTips8: "Tip: If the imported teacher's user ID, cell phone, or email has already registered a TEAM Model account, the system will automatically invite the teacher to join the school.",
         importTips9: 'Select or drag files to this area to import',
+        impText: '無效數據(沒有名字):',
         impText1: 'No. of imported:',
         impText2: 'No. of only name is imported:',
         impText3: 'No. of auto-invite by system:',
@@ -5594,7 +5607,6 @@ const LANG_EN_US = {
         ach_text10: 'Currently Class',
         ach_text11: 'Total Number',
         ach_text12: 'Back',
-
         ach_table_text1: 'Grade Ranking',
         ach_table_text2: 'Total Score',
         ach_table_text3: 'Average Score',
@@ -5611,7 +5623,6 @@ const LANG_EN_US = {
         ach_table_text14: 'Progressive Class',
         ach_table_text15: 'Regressive Class',
         ach_table_text16: 'Stable Class',
-
         ach_chart_text1: 'Sort by',
         ach_chart_text2: 'Default sort',
         ach_chart_text3: 'Score from high to low',
@@ -5644,7 +5655,6 @@ const LANG_EN_US = {
         ta_title2: 'Grade Single-question Scoring Rate Statistics',
         ta_title3: 'Question Analysis Summary Table',
         ta_title4: 'Question Scoring Rate Table',
-
         ta_text1: 'Area',
         ta_text2: 'Area Characteristics',
         ta_text3: 'Number Of Question',
@@ -5654,7 +5664,6 @@ const LANG_EN_US = {
         ta_text7: 'The test questions may contain abnormal components and need partial correction',
         ta_text8: 'The difficulty of test questions is high, which is suitable for distinguishing students with high achievement',
         ta_text9: 'The test questions contain abnormal components, which may be wrong in data or unclear in meaning, and must be modified',
-
         ta_chart_text1: 'Question',
         ta_chart_text2: 'Correctly Answered Rate',
         ta_chart_text3: 'Stability',
@@ -5663,7 +5672,6 @@ const LANG_EN_US = {
         ta_chart_text6: 'District Scoring Rate',
         ta_chart_text7: 'Maximum Value',
         ta_chart_text8: 'Minimum Value',
-
         ta_table_text1: 'No.',
         ta_table_text2: 'Type',
         ta_table_text3: 'Key Concept',
@@ -5675,7 +5683,6 @@ const LANG_EN_US = {
         ta_table_text9: 'District',
         ta_table_text10: 'High Group',
         ta_table_text11: 'Low Group',
-
         ta_table_tip1: '* Unit: Scoring Rate',
         ta_table_tip2: '* R1-R6: Ranking Range',
 
@@ -5687,22 +5694,18 @@ const LANG_EN_US = {
         ka_title5: 'Key Concept Scoring Details',
         ka_title6: 'Incorrectly Answered Question Rate Relation Table',
         ka_title7: 'Key Concept Scoring Rate Distribution Chart',
-
         ka_text1: 'Current key concept set',
         ka_text2: 'Current key concept',
         ka_text3: 'Current cognitive level',
         ka_text4: 'Cognitive Level Ratio Status',
-
         ka_chart_text1: 'Switch to histogram',
         ka_chart_text2: 'Switch to radar',
-
         ka_radar_text1: 'Remember',
         ka_radar_text2: 'Apply',
         ka_radar_text3: 'Analyze',
         ka_radar_text4: 'Create',
         ka_radar_text5: 'Evaluate',
         ka_radar_text6: 'Understand',
-
         ka_table_text1: 'Key Concept',
         ka_table_text2: 'Cognitive Level',
         ka_table_text3: 'Grade Scoring Rate',
@@ -5714,7 +5717,6 @@ const LANG_EN_US = {
         ka_table_text9: 'Incorrectly answered question person-time',
         ka_table_text10: 'PH Incorrectly answered question person-time',
         ka_table_text11: 'PL Incorrectly answered question person-time',
-
         ka_tip1: '* PH: High Group / LL: Low Group',
 
         // LevelAnalysis.vue
@@ -5742,7 +5744,6 @@ const LANG_EN_US = {
         ql_text13: 'Return',
         ql_text14: 'Connecting Questions',
         ql_text15: 'Matching Question',
-
         baseExport: {
             title: 'Select the form to export',
             checkAll: 'Select All',

+ 15 - 14
TEAMModelOS/ClientApp/public/lang/zh-CN.js

@@ -1102,7 +1102,6 @@ const LANG_ZH_CN = {
         orderTip2: '(例:Ⅰ、Ⅱ、Ⅲ、Ⅳ、Ⅴ......)',
         order3: '中文小写',
         orderTip3: '例:一、二、三、四、五......',
-
         paperTag: '试卷标签',
         paperTagPlace: '选择标签或者手动输入后回车创建新标签',
         useTip: '请至少保留一种试题用途',
@@ -1332,7 +1331,6 @@ const LANG_ZH_CN = {
             warningTips5: '抱歉,文档解析失败!',
             tips6: '操作失败,请先完善当前学段的科目信息!',
             tips7: '操作失败,请先完善当前学段的年级信息!'
-
         },
         createPaper: {
             setAutoConditions: '设置自动出题条件',
@@ -3656,6 +3654,7 @@ const LANG_ZH_CN = {
         addErr: '添加失败',
         updErr: '修改失败',
         sltClassTips: '请设置班级',
+        setNoErr: '学生座位号不能为空',
         classErr: '请设置学生所在班级',
         pwErr: '密码不能为空',
         nameErr: '学生姓名不能为空',
@@ -3728,6 +3727,16 @@ const LANG_ZH_CN = {
             vote: '投票',
             survey: '问卷',
             homework: '作业',
+            title: {
+                classRecord: "老师发布的课堂记录",
+                activity: "老师发布的活动",
+                notice1: "班级公告",
+                notice2: "课程公告",
+                exam: "评测成绩分析",
+                homework: "作业评分",
+                classScore: "课例记分",
+            },
+            toLook: "现在去看",
         },
         public: {
             noData: '暂无数据',
@@ -3750,6 +3759,7 @@ const LANG_ZH_CN = {
             hour: "时",
             minute: "分",
             mustFile: "必须上传作业",
+            uploadTime: "上传时间",
         },
         type: {
             home: "首页",
@@ -4543,6 +4553,9 @@ const LANG_ZH_CN = {
             wrongNum: "错误次数",
         },
         myAchievement: {
+            examAch: "评测成绩",
+            hwAch: "作业成绩",
+            cusAch: "老师给分",
             examMode: "评测模式",
             examIn: "发布来源",
             name: "名称",
@@ -5117,7 +5130,6 @@ const LANG_ZH_CN = {
         props6: '文件上传成功!',
         props7: '存储空间不足!',
         uploadText: '点击或者拖拽上传',
-
         resTips: 'HiTeach生成的课件,只支持HTEX格式的教材预览',
         space: '可用空间:',
         calcing: '计算中...',
@@ -5595,7 +5607,6 @@ const LANG_ZH_CN = {
         ach_text10: '当前班级',
         ach_text11: '总人数',
         ach_text12: '返回',
-
         ach_table_text1: '年级排名',
         ach_table_text2: '总分',
         ach_table_text3: '平均分',
@@ -5612,7 +5623,6 @@ const LANG_ZH_CN = {
         ach_table_text14: '进步班级',
         ach_table_text15: '退步班级',
         ach_table_text16: '稳定班级',
-
         ach_chart_text1: '排序方式',
         ach_chart_text2: '默认排序',
         ach_chart_text3: '分数从高到低',
@@ -5645,7 +5655,6 @@ const LANG_ZH_CN = {
         ta_title2: '年级单题得分率统计',
         ta_title3: '试题分析总表',
         ta_title4: '试题得分率表',
-
         ta_text1: '区域',
         ta_text2: '区域特性',
         ta_text3: '题数',
@@ -5655,7 +5664,6 @@ const LANG_ZH_CN = {
         ta_text7: '试题可能含有异质成分在内,需要局部修正',
         ta_text8: '试题困难度较高,适合区分高成就者学生',
         ta_text9: '试题含有异质成分,可能数据错误或者题意不清,必须加以修改',
-
         ta_chart_text1: '试题',
         ta_chart_text2: '答对率',
         ta_chart_text3: '稳定度',
@@ -5664,7 +5672,6 @@ const LANG_ZH_CN = {
         ta_chart_text6: '区级得分率',
         ta_chart_text7: '最大值',
         ta_chart_text8: '最小值',
-
         ta_table_text1: '题号',
         ta_table_text2: '题型',
         ta_table_text3: '知识点',
@@ -5676,7 +5683,6 @@ const LANG_ZH_CN = {
         ta_table_text9: '区级',
         ta_table_text10: '高分组',
         ta_table_text11: '低分组',
-
         ta_table_tip1: '* 单位:得分率',
         ta_table_tip2: '* R1-R6:排名区间',
 
@@ -5688,22 +5694,18 @@ const LANG_ZH_CN = {
         ka_title5: '知识点得分详情',
         ka_title6: '错题率关系表',
         ka_title7: '知识点得分率分布图',
-
         ka_text1: '当前知识块',
         ka_text2: '当前知识点',
         ka_text3: '当前认知层次',
         ka_text4: '认知层次占比情况',
-
         ka_chart_text1: '切换柱状图',
         ka_chart_text2: '切换雷达图',
-
         ka_radar_text1: '知识',
         ka_radar_text2: '应用',
         ka_radar_text3: '分析',
         ka_radar_text4: '综合',
         ka_radar_text5: '评鉴',
         ka_radar_text6: '理解',
-
         ka_table_text1: '知识点',
         ka_table_text2: '认知层次',
         ka_table_text3: '年级得分率',
@@ -5715,7 +5717,6 @@ const LANG_ZH_CN = {
         ka_table_text9: '错题人次',
         ka_table_text10: 'PH错题人次',
         ka_table_text11: 'PL错题人次',
-
         ka_tip1: '* PH:高分区段 / PL:低分区段',
 
         // LevelAnalysis.vue

+ 15 - 17
TEAMModelOS/ClientApp/public/lang/zh-TW.js

@@ -608,7 +608,6 @@ const LANG_ZH_TW = {
     },
     // 课程管理
     cusMgt: {
-        //ManageCourse.vue
         searchHolder: '搜尋',
         delBatch: '批量刪除',
         delCus: '刪除課程',
@@ -2087,7 +2086,6 @@ const LANG_ZH_TW = {
     },
     // 活动模块
     learnActivity: {
-        //MgtSchoolEva.vue
         noStartTimeTip:'不設置則默認為立即發佈',
         school: '校',
         area: '區',
@@ -3039,7 +3037,6 @@ const LANG_ZH_TW = {
     },
     // 基础信息
     schoolBaseInfo: {
-        // SystemSetting.vue
         commonset: '通用設定',
         pdMgt: '學制管理',
         cgMgt: '學院管理',
@@ -3730,6 +3727,16 @@ const LANG_ZH_TW = {
             vote: '投票',
             survey: '問卷',
             homework: '作業',
+            title: {
+                classRecord: "老師發佈的課堂記錄",
+                activity: "老師發佈的活動",
+                notice1: "班級公告",
+                notice2: "課程公告",
+                exam: "評測成績分析",
+                homework: "作業評分",
+                classScore: "課例記分",
+            },
+            toLook: "現在去看",
         },
         public: {
             noData: '暫無資料',
@@ -3752,6 +3759,7 @@ const LANG_ZH_TW = {
             hour: "時",
             minute: "分",
             mustFile: "必須上傳作業",
+            uploadTime: "上傳時間",
         },
         type: {
             home: "首頁",
@@ -4545,6 +4553,9 @@ const LANG_ZH_TW = {
             wrongNum: "錯誤次數",
         },
         myAchievement: {
+            examAch: "評量成績",
+            hwAch: "作業成績",
+            cusAch: "老師給分",
             examMode: "評量模式",
             examIn: "發佈來源",
             name: "名稱",
@@ -5119,7 +5130,6 @@ const LANG_ZH_TW = {
         props6: '檔案上傳成功!',
         props7: '儲存空間不足!',
         uploadText: '點按或者拖移上傳',
-
         resTips: 'HiTeach生成的教材,只支援HTEX格式',
         space: '可用空間:',
         calcing: '計算中…',
@@ -5435,6 +5445,7 @@ const LANG_ZH_TW = {
         importTips7: '5. note: 教師備註內容,選填;',
         importTips8: '溫馨提示:如果匯入的教師用戶編號,或者匯入的手機或信箱已註冊醍摩豆帳號,系統會自動邀請老師加入學校。',
         importTips9: '點擊或者拖拽文件匯入',
+        impText: '無效數據(沒有名字):',
         impText1: '匯入總人數:',
         impText2: '僅匯入姓名:',
         impText3: '系統將自動邀請:',
@@ -5596,7 +5607,6 @@ const LANG_ZH_TW = {
         ach_text10: '當前班級',
         ach_text11: '總人數',
         ach_text12: '返回',
-
         ach_table_text1: '年級排名',
         ach_table_text2: '總分',
         ach_table_text3: '平均分數',
@@ -5613,7 +5623,6 @@ const LANG_ZH_TW = {
         ach_table_text14: '進步班級',
         ach_table_text15: '退步班級',
         ach_table_text16: '穩定班級',
-
         ach_chart_text1: '排序方式',
         ach_chart_text2: '預設排序',
         ach_chart_text3: '分數從高到低',
@@ -5646,7 +5655,6 @@ const LANG_ZH_TW = {
         ta_title2: '年級單題得分率統計',
         ta_title3: '試題分析總表',
         ta_title4: '試題得分率表',
-
         ta_text1: '區域',
         ta_text2: '區域特性',
         ta_text3: '題數',
@@ -5656,7 +5664,6 @@ const LANG_ZH_TW = {
         ta_text7: '試題可能含有異質成分在內需要局部修正',
         ta_text8: '試題困難度較高適合區分高成就學生',
         ta_text9: '試題含有異質成分可能數據錯誤或者題意不清必須加以修改',
-
         ta_chart_text1: '試題',
         ta_chart_text2: '答對率',
         ta_chart_text3: '穩定度',
@@ -5665,7 +5672,6 @@ const LANG_ZH_TW = {
         ta_chart_text6: '區級得分率',
         ta_chart_text7: '最大值',
         ta_chart_text8: '最小值',
-
         ta_table_text1: '題號',
         ta_table_text2: '題型',
         ta_table_text3: '知識點',
@@ -5677,7 +5683,6 @@ const LANG_ZH_TW = {
         ta_table_text9: '區級',
         ta_table_text10: '高分组',
         ta_table_text11: '低分组',
-
         ta_table_tip1: '* 組織:得分率',
         ta_table_tip2: '* R1-R6:成就區分組',
 
@@ -5689,22 +5694,18 @@ const LANG_ZH_TW = {
         ka_title5: '知識點得分詳情',
         ka_title6: '錯題率關係表',
         ka_title7: '知識點得分率分佈圖',
-
         ka_text1: '當前知識塊',
         ka_text2: '當前知識點',
         ka_text3: '當前認知層次',
         ka_text4: '認知層次占比情况',
-
         ka_chart_text1: '切換長條圖',
         ka_chart_text2: '切換雷達圖',
-
         ka_radar_text1: '記憶',
         ka_radar_text2: '應用',
         ka_radar_text3: '分析',
         ka_radar_text4: '創造',
         ka_radar_text5: '評鑑',
         ka_radar_text6: '理解',
-
         ka_table_text1: '知識點',
         ka_table_text2: '認知層次',
         ka_table_text3: '年級得分率',
@@ -5716,7 +5717,6 @@ const LANG_ZH_TW = {
         ka_table_text9: '錯題人次',
         ka_table_text10: 'PH錯題人次',
         ka_table_text11: 'PL錯題人次',
-
         ka_tip1: '* PH:高分組 / PL:低分組',
 
         // LevelAnalysis.vue
@@ -5744,7 +5744,6 @@ const LANG_ZH_TW = {
         ql_text13: '返回',
         ql_text14: '連線題',
         ql_text15: '配合題',
-
         baseExport: {
             title: '選擇要匯出的表格',
             checkAll: '全選',
@@ -5765,7 +5764,6 @@ const LANG_ZH_TW = {
         paperSubject: '試卷學科',
         paperItemsCount: '試卷題數',
         backUp: '回到上層'
-
     },
     // 研修活动
     train: {

+ 1 - 1
TEAMModelOS/ClientApp/src/components/coursemgt/StudentList.vue

@@ -28,7 +28,7 @@
                         <PersonalPhoto :name="row.name" :picture="row.picture"></PersonalPhoto>
                     </template>
                     <template slot-scope="{ row }" slot="gradeName">
-                        <span>{{ $jsFn.getGradeNameByYear(schoolBase, searchPeriod, row.classYear) }}</span>
+                        <span>{{ $jsFn.getGradeNameByYear(row.classYear) }}</span>
                     </template>
                     <template slot-scope="{ row }" slot="classId">
                         <span>{{ getClassName(row.classId)}}</span>

+ 165 - 0
TEAMModelOS/ClientApp/src/components/student-web/HomeView/ChartHome/ClassPoint.vue

@@ -0,0 +1,165 @@
+<template>
+    <div class="class-echarts">
+        <div class="home-title-name">
+            {{ $t("studentWeb.home.title.classScore") }}
+        </div>
+        <div id="classPoint"></div>
+        <div class="typeAll">
+            <div class="typeDef" @click="changeType(false)">
+                <span :class="{'activeBg': !type}"></span>
+                <span>{{ $t("studentWeb.public.school") }}</span>
+            </div>
+            <div class="typeDef" @click="changeType(true)">
+                <span :class="{'activeBg': type}"></span>
+                <span>{{ $t("studentWeb.public.private") }}</span>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    name: "HomeworkPoint",
+    data() {
+        return {
+            type: false, //个人的类型
+            school: ["数学", "语文", "英语", "化学", "生物", "物理", "地理"],
+            private: ["个人", "培训课", "健身课", "鉴赏课", "解剖课", "盆栽课", "人文历史概述"],
+            schoolData: ['87', '75', '100', '12', '46', 97, 57],
+            privateData: ['55', '99', '12', '74', '88', 37, 67],
+        }
+    },
+    methods: {
+        setEcharts() {
+            let myChart = this.$echarts.init(document.getElementById("classPoint"))
+            let option = {
+                color: ["#5470C6", "#91CC75", '#00905a'],
+                /* title: {
+                    text: this.$t('studentWeb.exam.chart.keyPointPerformance'),
+                    left: 'left',
+                    textStyle: {
+                        // fontWeight: "normal",
+                        fontSize: "14",
+                    }
+                }, */
+                /* legend: {
+                    data: ["罗老师", "陈老师", "辅导员"],
+                    bottom: 0,
+                }, */
+                grid: {
+                    top: '10%',
+                    bottom: '15%',
+                    // left: '80',
+                    // right: '80',
+                },
+                dataZoom: [
+                    {
+						'show': true,
+						'height': 3,
+						'xAxisIndex': [0],
+						bottom: 5,
+						'start': 0,
+						'end': 100,
+						handleIcon: 'M512 497.821538m-418.264615 0a418.264615 418.264615 0 1 0 836.52923 0 418.264615 418.264615 0 1 0-836.52923 0Z',
+						handleSize: '160%',
+						handleStyle: {
+							color: '#d3dee5'
+						},
+						textStyle: {
+							color: '#717171'
+						},
+						// borderColor: '#90979c'
+					}, {
+						'type': 'inside',
+						'show': true,
+						'height': 15,
+						'start': 0,
+						'end': 100
+					}
+                ],
+                xAxis: {
+                    show: true,
+                    // name:'作业次数',
+                    nameLocation: 'end',
+                    type: 'category',
+                    data: this.type ? this.private : this.school,
+                    axisLine: {
+                        lineStyle: {
+                            color: "#AAA"
+                        }
+                    },
+                    axisLabel: {
+                        rotate: 0
+                    }
+                },
+                yAxis: {
+                    // name:'正确率',
+                    type: 'value',
+                    axisLine: {
+                        lineStyle: {
+                            color: "#AAA"
+                        }
+                    },
+                },
+                tooltip: {
+                    trigger: 'axis',
+                    padding: [4, 12],
+                },
+                series: [
+                    {
+                        name: '罗老师',
+                        type: 'line',
+                        data: this.type ? this.privateData : this.schoolData
+                    }
+                ],
+            }
+            myChart.setOption(option)
+        },
+        changeType(type) {
+            this.type = type
+            this.setEcharts()
+        },
+    },
+    mounted () {
+        this.setEcharts()
+    }
+}
+</script>
+
+<style lang="less" scoped>
+#classPoint {
+    width: 100%;
+    height: 235px;
+}
+.class-echarts {
+    .typeAll {
+        display: flex;
+        justify-content: center;
+
+        & > div:first-child {
+            margin-right: 20px;
+        }
+
+        .typeDef {
+            cursor: pointer;
+            display: flex;
+            align-items: center;
+            font-size: 12px;
+
+            & > span:first-of-type {
+                display: inline-block;
+                background: #ccc;
+                height: 12px;
+                width: 20px;
+                margin-right: 5px;
+                border-radius: 4px;
+            }
+        }
+
+        .activeBg {
+            background-color: #00ad6cd1 !important;
+            // color: white;
+        }
+    }
+}
+</style>

+ 270 - 0
TEAMModelOS/ClientApp/src/components/student-web/HomeView/ChartHome/ExamPerform.vue

@@ -0,0 +1,270 @@
+<template>
+    <div class="exam-echarts">
+        <div class="home-title-name">
+            {{ $t("studentWeb.home.title.exam") }}
+        </div>
+        <template v-id="nowRadar.length">
+            <div id="examPerform"></div>
+        </template>
+        <div v-show="!nowRadar.length" class="no-data">
+            <img src="../noData.png" alt="">
+            <p>暂没有数据</p>
+        </div>
+        <div class="typeAll">
+            <div class="typeDef" @click="changeType(false)">
+                <span :class="{'activeBg': !type}"></span>
+                <span>{{ $t("studentWeb.public.school") }}</span>
+            </div>
+            <div class="typeDef" @click="changeType(true)">
+                <span :class="{'activeBg': type}"></span>
+                <span>{{ $t("studentWeb.public.private") }}</span>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import { mapState } from 'vuex'
+export default {
+    name: "ExamPerform",
+    data() {
+        return {
+            type: false, //个人的类型
+            school: [],
+            privates: [],
+            schoolData: [{
+                name: "",
+                value: []
+            }],
+            privateData: [{
+                name: "",
+                value: []
+            }],
+            nowRadar: [],
+        }
+    },
+    methods: {
+        getExamAch() {
+            let param = {
+                userid: this.userInfo.sub,
+                userType: "",
+                school: this.userInfo.azp,
+                type: 'Exam',
+                continuationToken: null,
+                // count: 20,
+            }
+            param.userType = this.userInfo.scope === "tmduser" ? "tmdid" : "schoolid"
+            this.$api.studentWeb.getExamAch(param).then(async res => {
+                /* 
+                    科目的数组,里面有总的分数百分比,总的评测次数
+                    [{
+                        id、name,
+                        total: 310%,
+                        num: 4,
+                        average: 0
+                    }]
+                    得出总的数据后,再算平均分
+                    average = (total / average) * 100
+                */
+                if(!res.code) {
+                    let examArr = {
+                        school: [],
+                        privates: [],
+                    }
+                    if(res.result.length) {
+                        res.result.forEach(item => {
+                            if(item.subject) {
+                                item.subject.forEach((sub, sIndex) => {
+                                    // 找出我的成绩
+                                    let myAch = item.result.filter(result => {
+                                        return result.sub === sub.id
+                                    })
+                                    let score = 0
+                                    if(myAch.length) {
+                                        myAch.forEach(myAch => {
+                                            let myId = myAch.sIds.findIndex(sId => {
+                                                return sId === this.userInfo.sub
+                                            })
+                                            if(myId != -1) {
+                                                score = myAch.sum[myId]
+                                            }
+                                        })
+                                    }
+                                    let subjectData = {
+                                        id: sub.id,
+                                        name: sub.name,
+                                        total: Number((score / item.point[sIndex]).toFixed(2)),
+                                        num: 1,
+                                        average: 0
+                                    }
+                                    if(item.owner === 'school') {
+                                        if(examArr.school.length) {
+                                            let subIndex = examArr.school.findIndex(sch => {
+                                                return sch.id === subjectData.id
+                                            })
+                                            if(subIndex != -1) {
+                                                examArr.school[subIndex].num += 1
+                                                examArr.school[subIndex].total += subjectData.total
+                                            } else {
+                                                examArr.school.push(subjectData)
+                                            }
+                                        } else {
+                                            examArr.school.push(subjectData)
+                                        }
+                                    } else if(item.owner === 'teacher') {
+                                        if(examArr.privates.length) {
+                                            let subIndex = examArr.privates.findIndex(sch => {
+                                                return sch.id === subjectData.id
+                                            })
+                                            if(subIndex != -1) {
+                                                examArr.privates[subIndex].num += 1
+                                                examArr.privates[subIndex].total += subjectData.total
+                                            } else {
+                                                examArr.privates.push(subjectData)
+                                            }
+                                        } else {
+                                            examArr.privates.push(subjectData)
+                                        }
+                                    }
+                                })
+                            }
+                        })
+                    }
+                    examArr.school.forEach(item => {
+                        this.school.push({
+                            max: 100,
+                            name: item.name
+                        })
+                        let average = Number((item.total / item.num * 100).toFixed(0))
+                        console.log(item.total, item.num, average);
+                        this.schoolData[0].value.push(average)
+                    })
+                    examArr.privates.forEach(item => {
+                        this.privates.push({
+                            max: 100,
+                            name: item.name
+                        })
+                        let average = Number((item.total / item.num * 100).toFixed(0))
+                        console.log(item.total, item.num, average);
+                        this.privateData[0].value.push(average)
+                    })
+                    this.nowRadar = this.school
+                    if(this.nowRadar.length) {
+                        this.setEcharts()
+                    }
+                }
+            })
+        },
+        setEcharts() {
+            let myChart = this.$echarts.init(document.getElementById("examPerform"), 'macarons')
+            let option = {
+                color: ["#5470C6", "#91CC75", '#00905a'],
+                /* title: {
+                    text: this.$t('studentWeb.exam.chart.keyPointPerformance'),
+                    left: 'left',
+                    textStyle: {
+                        // fontWeight: "normal",
+                        fontSize: "14",
+                    }
+                }, */
+                /* legend: {
+                    data: [this.$t("studentWeb.exam.chart.me"), this.$t("studentWeb.exam.chart.participantClass"), this.$t("studentWeb.exam.chart.allClass")],
+                    bottom: 0,
+                }, */
+                grid: {
+                    top: '10%',
+                    bottom: '15%',
+                    // left: '80',
+                    // right: '80',
+                },
+                tooltip: {
+                    trigger: 'item',
+                    padding: [4, 12],
+                },
+                radar: {
+                    // shape: 'circle',
+                    indicator: this.nowRadar
+                },
+                series: [
+                    {
+                        name: '科目平均分',
+                        type: 'radar',
+                        data: this.type ? this.privateData : this.schoolData
+                    },
+                ],
+            }
+            myChart.setOption(option)
+        },
+        changeType(type) {
+            this.type = type
+            this.nowRadar = type ? this.privates : this.school
+            if(this.nowRadar.length) {
+                this.$nextTick(() => {
+                    this.setEcharts()
+                })
+            }
+        },
+    },
+    mounted () {
+        this.getExamAch()
+    },
+    computed: {
+        ...mapState({
+            userInfo: state => state.userInfo,
+        })
+    }
+}
+</script>
+
+<style lang="less" scoped>
+#examPerform {
+    width: 100%;
+    height: 235px;
+}
+.exam-echarts {
+    position: relative;
+
+    .typeAll {
+        display: flex;
+        justify-content: center;
+
+        & > div:first-child {
+            margin-right: 20px;
+        }
+
+        .typeDef {
+            cursor: pointer;
+            display: flex;
+            align-items: center;
+            font-size: 12px;
+
+            & > span:first-of-type {
+                display: inline-block;
+                background: #ccc;
+                height: 12px;
+                width: 20px;
+                margin-right: 5px;
+                border-radius: 4px;
+            }
+        }
+
+        .activeBg {
+            background-color: #00ad6cd1 !important;
+            // color: white;
+        }
+    }
+    .no-data {
+        background-color: #fff;
+        width: 100%;
+        height: 235px;
+        position: absolute;
+        top: 30px;
+        text-align: center;
+        padding-top: 35px;
+
+        img {
+            width: 50%;
+        }
+    }
+}
+</style>

+ 263 - 0
TEAMModelOS/ClientApp/src/components/student-web/HomeView/ChartHome/HomeworkPoint.vue

@@ -0,0 +1,263 @@
+<template>
+    <div class="homework-echarts">
+        <div class="home-title-name">
+            {{ $t("studentWeb.home.title.homework") }}
+        </div>
+        <div id="homeworkPoint"></div>
+    </div>
+</template>
+
+<script>
+import { mapState } from 'vuex'
+export default {
+    name: "HomeworkPoint",
+    data() {
+        return {
+            hwAch: []
+        }
+    },
+    computed: {
+        ...mapState({
+            userInfo: state => state.userInfo,
+        })
+    },
+    methods: {
+        getHwAch() {
+            let param = {
+                userid: this.userInfo.sub,
+                userType: "",
+                school: this.userInfo.azp,
+                type: 'Homework',
+                continuationToken: null,
+                // count: 20,
+            }
+            param.userType = this.userInfo.scope === "tmduser" ? "tmdid" : "schoolid"
+            this.$api.studentWeb.getHwAch(param).then(async res => {
+                let hwnum = []
+                let teaId = []
+                res.works.forEach(item => {
+                    teaId.push(item.createId)
+                    let haveTea = hwnum.findIndex(tea => {
+                        return tea.createId === item.createId
+                    })
+                    // 没有这个老师的数据
+                    if(haveTea === -1) {
+                        hwnum.push({
+                            createId: item.createId,
+                            score: [item.score.length ? item.score[0].score : 0]
+                        })
+                    } else {
+                        // 有这个老师的数据,只需要往score添加这次的成绩
+                        hwnum[haveTea].score.push(item.score.length ? item.score[0].score : 0)
+                    }
+                })
+                let teaName = await this.getTeacherName(teaId)
+                hwnum.forEach(item => {
+                    let tName = teaName.find(tea => {
+                        return tea.id === item.createId
+                    })
+                    item.name = tName ? tName.name : '-'
+                    this.hwAch.push(item)
+                })
+                this.setEcharts()
+            })
+        },
+        setEcharts() {
+            // legend名字
+            let legendData = []
+            // 最大次数
+            let maxNum = 0
+            this.hwAch.forEach(item => {
+                legendData.push(item.name)
+                maxNum = item.score.length > maxNum ? item.score.length : maxNum
+            });
+            // x轴的类别
+            let xAxisData = []
+            for (let i = 0; i < maxNum; i++) {
+                xAxisData.push(`第${i + 1}次`)
+            }
+            // 补充到最大次数的数据
+            let newAch = []
+            this.hwAch.map(item => {
+                if(item.score.length < maxNum) {
+                    let new111 = new Array(maxNum - item.score.length).fill(0)
+                    newAch.push({
+                        createId: item.createId,
+                        score: item.score.concat(new111)
+                    })
+                } else {
+                    newAch.push(item)
+                }
+            });
+            // 成绩数组
+            let tasfdsf = []
+            let newArr = new Array(maxNum)
+            this.hwAch.forEach((item, index) => {
+                tasfdsf.push([])
+                item.score.forEach((score, sIndex) => {
+                    tasfdsf[index].push(score)
+                })
+            });
+            let seriesData = []
+            this.hwAch.forEach((item, index) => {
+                seriesData.push(
+                    {
+                        name: item.name,
+                        symbol: "circle",
+                        // symbolSize: 12,
+                        type: "line",
+                        smooth: false,
+                        data: tasfdsf[index].concat(newArr.slice(0, maxNum - tasfdsf[index].length)),
+                    },
+                    {
+                        name: item.name,
+                        symbol: "circle",
+                        // symbolSize: 12,
+                        type: "line",
+                        smooth: false,
+                        itemStyle: {
+                            normal: {
+                                // color: "#95EBE1",
+                                lineStyle: {
+                                    // width: 2,
+                                    type: "dashed",
+                                },
+                            },
+                        },
+                        data: newArr.slice(0, item.score.length - 1).concat(newAch[index].score.slice(tasfdsf[index].length - 1, maxNum)),
+                    },
+                )
+            })
+            let myChart = this.$echarts.init(document.getElementById("homeworkPoint"), 'macarons')
+            let option = {
+                // color: ["#5470C6", "#5470C6", "#91CC75", "#91CC75", '#00905a', '#00905a'],
+                /* title: {
+                    text: this.$t('studentWeb.exam.chart.keyPointPerformance'),
+                    left: 'left',
+                    textStyle: {
+                        // fontWeight: "normal",
+                        fontSize: "14",
+                    }
+                }, */
+                grid: {
+                    top: '10%',
+                    bottom: '21%',
+                    // left: '80',
+                    // right: '80',
+                },
+                legend: {
+                    data: legendData,
+                    // data: ["罗老师", "陈老师", "辅导员"],
+                    bottom: 0,
+                },
+                dataZoom: [
+                    {
+						'show': true,
+						'height': 3,
+						'xAxisIndex': [0],
+						bottom: 25,
+						'start': 0,
+						'end': 100,
+						handleIcon: 'M512 497.821538m-418.264615 0a418.264615 418.264615 0 1 0 836.52923 0 418.264615 418.264615 0 1 0-836.52923 0Z',
+						handleSize: '160%',
+						handleStyle: {
+							color: '#d3dee5'
+						},
+						textStyle: {
+							color: '#717171'
+						},
+						// borderColor: '#90979c'
+					}, {
+						'type': 'inside',
+						'show': true,
+						'height': 15,
+						'start': 0,
+						'end': 100
+					}
+                ],
+                xAxis: {
+                    show: true,
+                    // name:'作业次数',
+                    nameLocation: 'end',
+                    type: 'category',
+                    data: xAxisData,
+                    axisLine: {
+                        lineStyle: {
+                            color: "#AAA"
+                        }
+                    },
+                    axisLabel: {
+                        rotate: 0
+                    }
+                },
+                yAxis: {
+                    // name:'正确率',
+                    type: 'value',
+                    axisLine: {
+                        lineStyle: {
+                            color: "#AAA"
+                        }
+                    },
+                },
+                tooltip: {
+                    trigger: 'axis',
+                    padding: [4, 12],
+                    formatter: function (params, ticket, callback) {
+                        var htmlStr = "";
+                        for (let i = 0; i < params.length; i++) {
+                            if (i === 0) {
+                                htmlStr += params[i].name + "<br/>"; //x轴的名称
+                            }
+                            if(!(i % 2)) {
+                                htmlStr += "<div>";
+                                htmlStr += '<span style="margin-right:5px;display:inline-block;width:10px;height:10px;border-radius:5px;background-color:' +
+                                            params[i].color + ';"></span>';
+                                htmlStr += params[i].seriesName + ":" + (params[i].data ? params[i].data : 0);
+                                htmlStr += "</div>";
+                            }
+                        }
+                        return htmlStr
+                    },
+                },
+                series: seriesData
+                /* [
+                    {
+                        name: '罗老师',
+                        type: 'line',
+                        data: ['87', '75', '100', '12', '46', 97, 57]
+                    },{
+                        name: '陈老师',
+                        type: 'line',
+                        data: ['42', '99', '75', '55', '76', 100, 88]
+                    },{
+                        name: '辅导员',
+                        type: 'line',
+                        data: ['97', '100', '86', '88', '33', 79, 56]
+                    },
+                ] */,
+            }
+            myChart.setOption(option)
+        },
+        getTeacherName(id) {
+            return new Promise((r, j) => {
+                this.$api.studentWeb.getTeacherName({id}).then(res => {
+                    r(res)
+                }).catch(e => {
+                    j(e)
+                })
+            })
+        },
+    },
+    mounted () {
+        this.getHwAch()
+        
+    }
+}
+</script>
+
+<style lang="less" scoped>
+#homeworkPoint {
+    width: 100%;
+    height: 253px;
+}
+</style>

+ 97 - 0
TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeViewnnnnew.less

@@ -0,0 +1,97 @@
+.home-view {
+    padding: 0.5rem 1.7rem;
+    
+    .home-card {
+        margin-top: 15px;
+        box-shadow: 0px 2px 13px rgba(0, 0, 0, 0.1);
+        border: 1px solid rgba(0, 0, 0, 0.2);
+        border-radius: 5px;
+        background-color: #fff;
+        padding: 15px;
+
+        &:hover {
+            box-shadow: 0px 2px 30px rgba(0, 0, 0, 0.2);
+        }
+    }
+
+    .home-list-title {
+        font-size: 16px;
+        // margin-bottom: 15px;
+        display: flex;
+        justify-content: space-between;
+
+        .list-type:not(:last-child) {
+            margin-right: 20px;
+        }
+    }
+    .home-head {
+        margin-top: 15px;
+        // display: flex;
+
+        .home-echarts {
+            // width: 100%;
+            // height: 400px;
+        }
+
+        /* .class-echarts,
+        .homework-echarts {
+            width: 40%;
+        }
+
+        .exam-echarts {
+            width: 30%;
+        } */
+    }
+
+    .no-data {
+        text-align: center;
+        min-height: 455px;
+        padding-top: 80px;
+
+        img {
+            width: 50%;
+        }
+    }
+
+    .no-data-notice {
+        
+        text-align: center;
+        min-height: 212px;
+        // padding-top: 40px;
+
+        img {
+            width: 40%;
+        }
+    }
+
+    .class-record {
+        display: flex;
+        justify-content: space-between;
+        margin-bottom: 20px;
+
+        & > div > p:first-child {
+            margin-bottom: 5px;
+        }
+
+        & > div:first-child {
+            & > p:first-child {
+                font-size: 18px;
+                font-weight: bold;
+            }
+        }
+
+        & > div:last-child{
+            text-align: right;
+        }
+
+        img {
+            width: 50%;
+        }
+    }
+}
+
+@media screen and (max-width: 520px) {
+    .home-view .home-list-title {
+        display: block;
+    }
+}

+ 509 - 0
TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeViewnnnnew.vue

@@ -0,0 +1,509 @@
+<template>
+    <div class="home-view">
+        <Loading v-show="isLoading" bgColor="rgba(0, 0, 0, 0.3)"></Loading>
+        <div class="home-head home-card">
+        <Row :gutter="30">
+            <Col :xs="24" :sm="12" :md="12" :lg="8">
+                <ExamPerform />
+            </Col>
+            <Col :xs="24" :sm="12" :md="12" :lg="8">
+                <HomeworkPoint />
+            </Col>
+            <Col :xs="24" :sm="12" :md="12" :lg="8">
+                <ClassPoint />
+            </Col>
+        </Row>
+        </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" style="height: 455px;">
+                        <vuescroll>
+                            <div v-for="(classRecord, cIndex) in classRecord" :key="cIndex" class="list-new">
+                                <div class="list-new-icon">
+                                    <img src="./noData.png" alt="">
+                                </div>
+                                <div class="list-new-test">
+                                    <p>{{ classRecord.name }}</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" style="height: 455px;">
+                        <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" class="tag-style"
+                                                    style="border-color: #499c8d; color: #499c8d;"
+                                                >
+                                                    {{ item.name }}
+                                                </span>
+                                            </span>
+                                        </span>
+                                        <span v-if="activity.className.length">
+                                            <span v-for="(clasNa, index) in activity.className" :key="index" class="tag-style"
+                                                style="border-color: #8f8787; color: #8f8787;">
+                                                {{ clasNa }}
+                                            </span>
+                                        </span>
+                                        <span class="tag-style" style="border-color: #6b6ba9; color: #6b6ba9;" v-if="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>去查看</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>
+                        <p class="home-title-name">{{ $t("studentWeb.home.title.notice1") }}</p>
+                        <div v-if="classNotice.length" style="height: 200px; margin-bottom: 10px;">
+                            <vuescroll>
+                                <div v-for="(cNotice, nIndex) in classNotice" :key="nIndex" class="list-new">
+                                    <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.name }}</span>
+                                        </p>
+                                        <p class="list-item-time">
+                                            {{ cNotice.time }}
+                                        </p>
+                                    </div>
+                                </div>
+                            </vuescroll>
+                        </div>
+                        <div v-else class="no-data-notice">
+                            <img src="./noData.png" alt="">
+                            <p>{{ $t("studentWeb.public.noData") }}</p>
+                        </div>
+                    </div>
+                    <div>
+                        <p class="home-title-name">{{ $t("studentWeb.home.title.notice2") }}</p>
+                        <div v-if="courseNotice.length" style="height: 200px; margin-bottom: 10px;">
+                            <vuescroll>
+                                <div v-for="(couNotice, nIndex) in courseNotice" :key="nIndex" class="list-new">
+                                    <div class="list-new-icon">
+                                        <Icon custom="iconfont icon-notify" size="30" />
+                                    </div>
+                                    <div class="list-new-test">
+                                        <p class="list-item-title">
+                                            <span>{{ couNotice.name }}</span>
+                                        </p>
+                                        <p style="font-size:12px; margin-top: 5px; word-break: keep-all;">
+                                            <span v-if="couNotice.className">
+                                                <span class="tag-style" style="border-color: #499c8d; color: #499c8d;">
+                                                    {{ couNotice.className }}
+                                                </span>
+                                            </span>
+                                            <span v-if="couNotice.teaName">
+                                                <span class="tag-style" style="border-color: #8f8787; color: #8f8787;">
+                                                    {{ couNotice.teaName }}
+                                                </span>
+                                            </span>
+                                        </p>
+                                        <p class="list-item-time">
+                                            {{ couNotice.time }}
+                                        </p>
+                                    </div>
+                                </div>
+                            </vuescroll>
+                        </div>
+                        <div v-else class="no-data-notice">
+                            <img src="./noData.png" alt="">
+                            <p>{{ $t("studentWeb.public.noData") }}</p>
+                        </div>
+                    </div>
+                </div>
+            </Col>
+        </Row>
+    </div>
+</template>
+
+<script>
+import ExamPerform from './ChartHome/ExamPerform.vue';
+import HomeworkPoint from './ChartHome/HomeworkPoint.vue';
+import ClassPoint from './ChartHome/ClassPoint.vue';
+import { mapState } from 'vuex';
+
+export default {
+    name: "HomeViewnnnnew",
+    components: {
+        ExamPerform,
+        HomeworkPoint,
+        ClassPoint,
+    },
+    // inject: ['reload'],
+    data() {
+        return {
+            MyNo: "1", //接收NavBar 選定的那一頁icon標示
+            MyName: "",
+            isLoading: false,
+            classRecord: [], //课堂记录
+            activityList: [], //活动
+            classNotice: [], //班级公告
+            courseNotice: [], //课程公告
+            countDown: null,
+            activityType: {
+                exam: 0,
+                homework: 0,
+                vote: 0,
+                survey: 0,
+            },
+            examAch: [],
+        }
+    },
+    mounted () {
+        this.MyName = this.$t("studentWeb.homeView-title")
+        this.$emit("onNavNo", this.MyNo)
+        this.$emit("onNavName", this.MyName)
+        this.getNotice()
+        this.getClaRecord()
+        this.getActivity()
+    },
+    methods: {
+        getNotice() {
+            this.courseNotice = [
+                /* {
+                    name: "测试",
+                    time: "2021-05-05 ~ 2021-05-06",
+                    content: "测试内容",
+                    className: "数学",
+                    teaName: "罗老师",
+                },{
+                    name: "测试",
+                    time: "2021-05-05 ~ 2021-05-06",
+                    content: "测试内容",
+                    className: "数学",
+                    teaName: "罗老师",
+                },{
+                    name: "测试",
+                    time: "2021-05-05 ~ 2021-05-06",
+                    content: "测试内容",
+                    className: "数学",
+                    teaName: "罗老师",
+                },{
+                    name: "测试",
+                    time: "2021-05-05 ~ 2021-05-06",
+                    content: "测试内容",
+                    className: "数学",
+                    teaName: "罗老师",
+                }, */
+            ]
+        },
+        getClaRecord() {
+            this.classRecord = [
+                /* {
+                    name: "罗老师的课堂记录",
+                    startTime: "2022-04-29",
+                    time: "00:10:58",
+                },
+                {
+                    name: "罗老师的课堂记录",
+                    startTime: "2022-04-29",
+                    time: "00:10:58",
+                },
+                {
+                    name: "罗老师的课堂记录",
+                    startTime: "2022-04-29",
+                    time: "00:10:58",
+                },
+                {
+                    name: "罗老师的课堂记录",
+                    startTime: "2022-04-29",
+                    time: "00:10:58",
+                },
+                {
+                    name: "罗老师的课堂记录",
+                    startTime: "2022-04-29",
+                    time: "00:10:58",
+                }, */
+            ]
+        },
+        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 path = item.type === 'Exam' ? '/studentWeb/examView' : (item.type === 'Homework' ? '/studentWeb/homeworkView' : '/studentWeb/eventView')
+            this.$router.push({
+                path,
+                query: {aId: item.id}
+            })
+        },
+    },
+    computed: {
+        ...mapState({
+            userInfo: state => state.userInfo,
+        })
+    },
+    beforeDestroy () {
+        clearInterval(this.countDown)
+        this.countDown = null
+    },
+}
+</script>
+
+<style lang="less" scoped>
+@import './HomeViewnnnnew.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;
+    }
+}
+</style>

BIN
TEAMModelOS/ClientApp/src/components/student-web/HomeView/noData.png


+ 51 - 11
TEAMModelOS/ClientApp/src/utils/js-fn.js

@@ -226,28 +226,24 @@ function dateFormat(timestamp) {
 
 /**
  * 根据学年获取年级名称
- * @param data 学校基础数据 schoolProfile.school_base
- * @param curPd 当前学段id
  * @param year 学年
  */
-function getGradeNameByYear(data, curPd, year) {
-    if (year && year > 0 && data && data.period && curPd) {
-        let pData = data.period.find(item => {
-            return item.id == curPd
-        })
-        if (pData) {
+function getGradeNameByYear(year) {
+    if (year && year > 0) {
+        let curPeriod = store.state.user?.curPeriod
+        if (curPeriod) {
             let date = new Date()
             let curYear = date.getFullYear()
             let month = date.getMonth() + 1
-            let start = pData.semesters.find(item => {
+            let start = curPeriod.semesters.find(item => {
                 return item.start == 1
             })
             // 根据入学月份确定当前年级和学级的关系
             if (start && month < start.month) {
                 curYear--
             }
-            let res = pData.grades[curYear - year]
-            if (curYear - year >= pData.grades.length) {
+            let res = curPeriod.grades[curYear - year]
+            if (curYear - year >= curPeriod.grades.length) {
                 return app.$t('schoolBaseInfo.graduated')
             }
             return res ? res : app.$t('schoolBaseInfo.untimed')
@@ -258,6 +254,49 @@ function getGradeNameByYear(data, curPd, year) {
         return '--'
     }
 }
+
+/**
+ * 根据学年获取年级信息
+ * @param year 学年
+ * @param periodId 学段id(非必填)
+ */
+function getGradeInfoByYear(year, periodId) {
+    if (year && year > 0) {
+        let curPeriod
+        if (periodId) {
+            curPeriod = store.state.user?.schoolProfile?.school_base?.period?.find(item => item.id == periodId)
+        } else {
+            curPeriod = store.state.user?.curPeriod
+        }
+        if (curPeriod) {
+            let date = new Date()
+            let curYear = date.getFullYear()
+            let month = date.getMonth() + 1
+            let start = curPeriod.semesters.find(item => {
+                return item.start == 1
+            })
+            // 根据入学月份确定当前年级和学级的关系
+            if (start && month < start.month) {
+                curYear--
+            }
+            let res = curPeriod.grades[curYear - year]
+            let gradeName
+            if (curYear - year >= curPeriod.grades.length) {
+                gradeName = app.$t('schoolBaseInfo.graduated')
+            }
+            gradeName = res ? res : app.$t('schoolBaseInfo.untimed')
+            return {
+                id: curYear - year,
+                name: gradeName
+            }
+        } else {
+            return undefined
+        }
+    } else {
+        return undefined
+    }
+}
+
 /**
  * 根据班级学年年级名称
  * @param data 学校基础数据 schoolProfile.school_base
@@ -341,6 +380,7 @@ export default {
     uuid,
     findChartIndex,
     getGradeNameByYear,
+    getGradeInfoByYear,
     getYearByGrade,
     dateFormat,
     timeFormat,

+ 42 - 6
TEAMModelOS/ClientApp/src/view/learnactivity/CreatePrivEva.vue

@@ -238,11 +238,12 @@ export default {
                 this.evaluationInfo.classes = []
             }
             //学校课程教学班
-            else if (this.evaluationInfo.scope == 'school' && this.evaluationInfo.targets.length && this.evaluationInfo.targets[0][1] == 'stulist') {
+            else if (this.evaluationInfo.scope == 'school' && this.evaluationInfo.targets.length && this.evaluationInfo.targets[0][1] == 'teach') {
                 this.evaluationInfo.stuLists = this.evaluationInfo.targets.map(item => {
                     return item[2]
                 })
                 this.evaluationInfo.classes = []
+                this.evaluationInfo.grades = []
             }
             // 学校课程行政班
             else {
@@ -250,15 +251,48 @@ export default {
                     return item[2]
                 })
                 this.evaluationInfo.stuLists = []
+                //补充年级信息
+                this.evaluationInfo.grades = []
+                let courseClassList = data.course?.children?.find(item => item.id == 'class')?.children
+                if (courseClassList && courseClassList.length) {
+                    let sltClass = courseClassList.filter(item => this.evaluationInfo.classes.includes(item.id))
+                    let grades = Array.from(new Set(sltClass?.map(item => item.year)))
+
+                    let gradesInfo = grades.map(item => {
+                        return this.$jsFn.getGradeInfoByYear(item, data.course.periodId)
+                    })
+                    gradesInfo = gradesInfo.filter(item => !!item)
+                    gradesInfo.forEach(item=>{
+                        item.id = item.id.toString()
+                    })
+                    this.evaluationInfo.grades = gradesInfo
+                }
             }
 
             //2、设置评测“学科”
             this.evaluationInfo.subjects = []
-            if (this.evaluationInfo.targets.length && data.course) {
-                this.evaluationInfo.subjects.push({
-                    id: data.course.id,
-                    name: data.course.name
-                })
+            // 个人课程用课程名称代替学科
+            if (this.evaluationInfo.scope == 'private') {
+                if (data.targets.length && data.course) {
+                    this.evaluationInfo.subjects.push({
+                        id: data.course.id,
+                        name: data.course.name
+                    })
+                }
+                this.evaluationInfo.period = undefined
+            }
+            //校本课程用课程关联的学生,并补充学段信息
+            else {
+                if (data.targets.length && data.course) {
+                    this.evaluationInfo.subjects.push({
+                        id: data.course.subjectId,
+                        name: data.course.subject
+                    })
+                    this.evaluationInfo.period = {
+                        id: data.course.periodId,
+                        name: data.course.period
+                    }
+                }
             }
         },
         /*
@@ -380,7 +414,9 @@ export default {
                 name: this.evaluationInfo.name,
                 creatorId: this.$store.state.userInfo.TEAMModelId,
                 type: this.evaluationInfo.type,
+                period: this.evaluationInfo.period,
                 subjects: this.evaluationInfo.subjects,
+                grades: this.evaluationInfo.grades,
                 papers: apiPapers,
                 examType: this.evaluationInfo.examType,
                 year: new Date().getFullYear(),

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

@@ -31,7 +31,7 @@
                         <div class="class-list-item-left">
                             <p style="color:var(--primary-text-color);font-size: 12px;">
                                 {{item.year ? item.year+$t('unit.gradeYear') : $t('schoolBaseInfo.noSet')}}
-                                <span v-show="item.year" style="color: var(--second-text-color)">{{`(${$jsFn.getGradeNameByYear(schoolBase, filterPeriod, item.year)})`}}</span>
+                                <span v-show="item.year" style="color: var(--second-text-color)">{{`(${$jsFn.getGradeNameByYear(item.year)})`}}</span>
                             </p>
                             <p class="class-name">
                                 <span class="class-id-tag">

+ 1 - 1
TEAMModelOS/ClientApp/src/view/student-account/stuMgt/ImportStudent.vue

@@ -94,7 +94,7 @@
                     <p>{{(row.pw == '' || row.pw == null)? '— —' : row.pw+''}}</p>
                 </template>
                 <template slot-scope="{ row }" slot="classYear">
-                    <p>{{ `${$jsFn.getGradeNameByYear(schoolBase, period, row.classYear)}(${row.classYear}${$t('unit.gradeYear')})` }}</p>
+                    <p>{{ `${$jsFn.getGradeNameByYear(row.classYear)}(${row.classYear}${$t('unit.gradeYear')})` }}</p>
                 </template>
                 <template slot-scope="{ row,index }" slot="status">
                     <!-- Excel 錯誤 -->

+ 1 - 1
TEAMModelOS/ClientApp/src/view/student-account/stuMgt/StuMgt.vue

@@ -73,7 +73,7 @@
                     </template>
                     <template slot-scope="{ row }" slot="gradeName">
                         <span :style="{color: row.classYear > 0 ? '#515a6e':'#ed4014'}">
-                            {{ row.classYear > 0 ? $jsFn.getGradeNameByYear(schoolBase, searchPeriod, row.classYear) : $t('stuAccount.noRelClass')}}
+                            {{ row.classYear > 0 ? $jsFn.getGradeNameByYear(row.classYear) : $t('stuAccount.noRelClass')}}
                         </span>
                     </template>
                     <template slot-scope="{ row }" slot="action">

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

@@ -0,0 +1,178 @@
+.myNav {
+    height: 45px;
+    line-height: 45px;
+    background-color: #FFF;
+    border-bottom: 1px solid #dcdee2;
+
+    display: flex;
+    justify-content: space-between;
+
+
+    .sidebar-toggle {
+        padding: 0px 10px;
+        position: relative;
+        top: -3px;
+        left: 10px;
+
+        .menu-icon {
+            color: rgb(2, 179, 90) !important;
+            cursor: pointer;
+        }
+
+        .menu-icon-close {
+            color: rgb(105, 105, 105) !important;
+        }
+    }
+
+    .mytitle {
+        padding: 0rem 1rem;
+        color: rgb(2, 179, 90);
+        font-weight: bolder;
+        position: relative;
+        font-size: 20px;
+    }
+
+    .no-show {
+        margin-left: 6px;
+    }
+
+    .tabIcon1 {
+        position: relative;
+        font-size: 18px;
+    }
+
+    .tabIcon2 {
+        position: relative;
+        font-size: 18px;
+        top: 2px;
+    }
+
+    .tabIcon3 {
+        position: relative;
+        font-size: 18px;
+        top: 1px;
+    }
+
+    .tabIcon4 {
+        position: relative;
+        font-size: 18px;
+        top: 1px;
+        margin-left: 4px;
+    }
+
+    .tab-list {
+        cursor: pointer;
+        margin: 0 20px;
+    }
+
+
+    .stu-photo {
+        margin: 0px 25px 0 10px;
+        cursor: pointer;
+        display: flex;
+
+        img {
+            margin-top: 5px;
+            border-radius: 50%;
+        }
+    }
+
+    .addClass {
+        margin-top: 8px;
+
+        button {
+            color: #ffffff;
+            background-color: #64AE16;
+            border-top-left-radius: 0;
+            border-bottom-left-radius: 0;
+        }
+    }
+
+    .profile-dropdown {
+
+        #stuPhoto {
+            margin: 0px 25px 0 10px;
+            cursor: pointer;
+            display: flex;
+
+            img {
+                border-radius: 50%;
+                margin-top: 5px;
+            }
+        }
+
+        &>p {
+            float: right;
+            margin-right: 48px;
+            font-weight: bold;
+        }
+
+        &:hover {
+            #profile-pop {
+                display: block;
+                position: fixed;
+                border-radius: 5px;
+                background-color: rgb(255, 255, 255);
+                z-index: 902;
+                top: 44px;
+                right: 15px;
+                width: 170px;
+                height: auto;
+                box-shadow: 1px 8px 20px rgba(0, 0, 0, 0.2);
+                padding: 2px 0px;
+            }
+        }
+    }
+
+
+    /***個人設定彈窗 */
+    #profile-pop {
+        display: none;
+
+        .profile-pop-item {
+            cursor: pointer;
+            font-weight: bold;
+            padding: 0px 10px;
+            // border-top: 1px solid rgba(0, 0, 0, 0.1);
+            color: #575757;
+
+            &:hover {
+                background: linear-gradient(-0.75turn, #fafafa, #d4ede1);
+                color: #03966a;
+                cursor: pointer;
+            }
+        }
+
+        .profile-name {
+            font-size: 12px;
+            padding: 0px 10px;
+            color: #03966a;
+            border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+            margin-bottom: 5px;
+        }
+
+        .profile-pop-icon {
+            width: 25px;
+            text-align: center;
+
+            &-1 {
+                font-size: 17px;
+            }
+
+            &-2 {
+                font-size: 15px;
+            }
+        }
+    }
+}
+
+@media screen and (max-width: 1367px) {
+    .myNav .no-show {
+        display: none;
+    }
+}
+@media screen and (max-width: 520px) {
+    .myNav .no-show-title {
+        display: none;
+    }
+}

+ 327 - 0
TEAMModelOS/ClientApp/src/view/student-web/AppNew.vue

@@ -0,0 +1,327 @@
+<template>
+    <div id="app" :style="{ 'background-color': pagebgc }">
+        <!--導航列-->
+        <div class="myNav">
+            <div>
+                <span @click="clickSidebarToggle()"
+                    v-if="MyNo != '1' && MyNo != '4' && MyNo != 'X' && MyNo != '7'"
+                    class="sidebar-toggle">
+                    <Icon class="menu-icon" type="md-menu"
+                        :class="{'menu-icon-close': this.$store.getters.getSidebarisOpen == false}" />
+                </span>
+                <span :class="['mytitle', {'no-show-title': MyNo === '1'}]">{{ MyName }}</span>
+            </div>
+            <div class="addClass" v-show="MyNo === '1'">
+                <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>
+            <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.courseList-title')">
+                        <svg-icon icon-class="course" class="tabIcon1" />
+                        <span class="no-show" v-show="MyNo != 2">{{ $t('studentWeb.course') }}</span>
+                    </MenuItem>
+                    <MenuItem name="5" to="/studentWeb/examView" :title="$t('studentWeb.type.exam')">
+                        <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')">
+                        <svg-icon icon-class="doc" class="tabIcon3" />
+                        <span class="no-show" v-show="MyNo != 6">{{ $t('studentWeb.type.homework') }}</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="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>
+                </Menu>
+                <!-- 头像 -->
+                <div class="profile-dropdown">
+                    <div id="stuPhoto" v-if="userInfo.picture">
+                        <img :src="userInfo.picture" alt="" width="35" height="35">
+                        <span style="margin-left: 5px;">{{ userInfo.name }}</span>
+                    </div>
+                    <div id="profile-pop">
+                        <p class="profile-name">{{ userInfo.name }} ({{ userInfo.studentId }})</p>
+                        <template v-if="windowWidth < 852">
+                            <div class="profile-pop-item" @click="goto('/studentWeb/homeView')">
+                                <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') }}
+                            </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>
+                        </template>
+                        <div class="profile-pop-item" @click="onSet">
+                            <svg-icon icon-class="setting" class="profile-pop-icon profile-pop-icon-2" />
+                            {{ $t("studentWeb.home.setting") }}
+                        </div>
+                        <div class="profile-pop-item" @click="onQuit">
+                            <svg-icon icon-class="logout" class="profile-pop-icon profile-pop-icon-1" />
+                            {{ $t("studentWeb.home.logout") }}
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <!--內容區-->
+        <div class="myContent">
+            <router-view @onNavNo="getNavNo"
+                         @onNavName="getNavName"
+                         @onMessage="getmessage"
+                         v-if="isRouterAlive">
+            </router-view>
+        </div>
+    </div>
+</template>
+
+<script>
+    import jwtDecode from 'jwt-decode'
+    import PersonalPhoto from '@/components/public/personalPhoto/Index.vue'
+    export default {
+        name: "App",
+        components: {
+            jwtDecode,
+            PersonalPhoto
+        },
+        provide() {
+            return {
+                reload: this.reload,
+            };
+        },
+        data() {
+            return {
+                courseID: "",
+                MyNo: "", //接收NavBar 選定的那一頁icon標示
+                MyName: "", //接收NavBar 那一頁的名字
+                isRouterAlive: true,
+                windowWidth: window.innerWidth,
+                windowHeight: window.innerHeight,
+                isTyping: false,
+                curRole: '',
+                users: '',
+                identity: sessionStorage.getItem('identity'),
+                userInfo: {},
+                isAddClass: false,
+                addClassNo: '',
+            };
+        },
+        computed: {
+            getRoleName() {
+                return val => {
+                    // return val === 'student' ? '学生' : '教师'
+                    return val === 'student' ? this.$t("studentWeb.home.student") : this.$t("studentWeb.home.teacher")
+                }
+            },
+            //判断用户权限
+            isTeacher() {
+                let state = false
+                if (this.users.roles.length) {
+                    for (let item of this.users.roles) {
+                        if (item == 'teacher' || item == 'admin') {
+                            state = true
+                        }
+                    }
+                }
+                return state
+            },
+            getSrvAdr() {
+                let id_token = localStorage.getItem("stu_id_token")
+                let auth_token = localStorage.getItem("stu_auth_token")
+                // 醍摩豆id传id,学校账号传auth
+                let params = this.$store.state.userInfo.scope === "tmduser" ? ('id=' + id_token) : ('auth=' + auth_token)
+                let srvAdr = this.$store.state.config.srvAdr // Global:国际站   China:正式站/测试站
+                let url = srvAdr === 'Global' ? this.$store.state.config.Global.irsUrl : this.$store.state.config.China.irsUrl
+				return `${url}?${params}`
+            },
+            pagebgc() {
+                if (this.MyNo == "1") {
+                    return "#f0f0f0";
+                } else {
+                    return ""
+                }
+            },
+        },
+        watch: {
+            courseID: function (value) {
+                if (value != "") {
+                    this.isTyping = true
+                } else if (value == "") {
+                    this.isTyping = false
+                }
+            },
+        },
+        created() {
+            this.getUsers();
+            this.$store.dispatch('user/checkStudentProfile');// 檢查學生的詳細資訊,刷新后同步localStorage数据
+        },
+        mounted() {
+            this.getStudentData()
+            this.$nextTick(() => {
+                window.addEventListener("resize", this.onResize);
+            });
+        },
+        beforeDestroy() {
+            window.removeEventListener("resize", this.onResize);
+        },
+        methods: {
+            sentcourseID() {
+                this.$store.commit('searchCourseIDforAdd', this.courseID.trim())
+            },
+            onResize() {
+                this.windowWidth = window.innerWidth;
+                this.windowHeight = window.innerHeight;
+            },
+            clickSidebarToggle() {
+                this.$store.commit("ToggleSidebar");
+            },
+            noData() {
+                this.$Message.warning(this.$t("studentWeb.public.notice"))
+            },
+            reload() {
+                // 刷新页面的作用
+                this.isRouterAlive = false;
+                this.$nextTick(() => (this.isRouterAlive = true));
+            },
+            getNavNo: function (MyNo) {
+                this.MyNo = MyNo;
+            },
+            getNavName: function (MyName) {
+                this.MyName = MyName;
+                if(MyName == this.$t("studentWeb.courseList-title") || MyName == this.$t("studentWeb.homeView-title")) {
+                    this.isAddClass = true
+                } else {
+                    this.isAddClass = false
+                }
+            },
+            getUsers() {
+                this.users = JSON.parse(decodeURIComponent(sessionStorage.userInfo, "utf-8"));
+                let data = jwtDecode(localStorage.getItem('stu_auth_token'))
+                if (data.name !== "") {
+                    this.$store.commit("setUserInfo", data)
+                    this.$store.commit("setStuUserInfo", data)
+                    sessionStorage.setItem("userInfo", encodeURIComponent(JSON.stringify(data)))
+                }
+                if (this.users.roles.length) {
+                    this.curRole = sessionStorage.getItem('identity')
+                }
+            },
+            getStudentData() {
+                this.userInfo = this.$store.getters.getStuUserInfo
+            },
+            onRoleSelect(val) {
+                if (sessionStorage.getItem('identity') != val) {
+                    this.curRole = val
+                    let path = val === 'student' ? '/studentWeb' : '/home'
+                    sessionStorage.setItem('identity', val)
+                    this.$router.push({ path: path })
+                }
+            },
+            onQuit() {
+                this.$store.commit('user/resetSchoolProfile')
+                this.$store.commit("ChangeItemName", null)
+                localStorage.removeItem('Item')
+                localStorage.removeItem('subjectNow')
+                localStorage.removeItem('examInfo')
+                localStorage.removeItem('paperInfo')
+                this.$User.logout()
+                this.$router.push({
+                    path: '/login'
+                })
+            },
+            onSet() {
+                this.$router.push({
+                    path: '/studentWeb/setting'
+                })
+            },
+            getmessage(val) {
+                this.userInfo = val
+                this.$forceUpdate()
+            },
+            // 加入课程
+            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.reload()
+                        } 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'))
+                        }
+                    })
+                }
+            },
+            goto(path, blank) {
+                if(blank) {
+                    window.open(path, '_blank');
+                } else {
+                    this.$router.push(path)
+                }
+            },
+        },
+    };
+</script>
+
+<style lang="less" scoped>
+@import "./App.less";
+</style>
+
+<style lang="less">
+@import "./AppiView.less";
+</style>

+ 55 - 0
TEAMModelOS/ClientApp/src/view/student-web/AppiView.less

@@ -0,0 +1,55 @@
+.myNav {
+    .ivu-menu-horizontal {
+        height: 45px !important;
+        // padding-top: 4px;
+        line-height: 45px !important;
+        // padding-bottom: 4px;
+
+        .ivu-menu-item {
+            padding: 0px 20px !important;
+            border-bottom: 3px solid transparent !important;
+            // bottom: 1px;
+        }
+    }
+
+    .ivu-menu-light.ivu-menu-horizontal .ivu-menu-item-active,
+    .ivu-menu-light.ivu-menu-horizontal .ivu-menu-item:hover,
+    .ivu-menu-light.ivu-menu-horizontal .ivu-menu-submenu-active,
+    .ivu-menu-light.ivu-menu-horizontal .ivu-menu-submenu:hover {
+        color: rgb(2, 179, 90) !important;
+        border-bottom: 3px solid rgb(2, 179, 90) !important;
+        transition: 0.5s;
+        // bottom: 2px;
+    }
+
+    .ivu-select-dropdown {
+        top: 39px !important;
+        // margin-right: 20px;
+        // margin-top: -13px;
+    }
+    .ivu-dropdown-menu{
+        min-width: 200px;
+    }
+
+    .ivu-dropdown {
+        margin-right: 20px;
+    }
+
+    .addClass {
+        .ivu-input-icon {
+            line-height: 30px;
+            right: 90px;
+        }
+
+        .ivu-input,
+        .ivu-btn {
+            height: 28px;
+        }
+    }
+}
+
+@media screen and (max-width: 1367px) {
+    .myNav .ivu-menu-horizontal .ivu-menu-item {
+        padding: 0 11px !important;
+    }
+}

+ 2 - 0
TEAMModelOS/Controllers/Both/GroupListController.cs

@@ -494,7 +494,9 @@ namespace TEAMModelOS.Controllers
                         {
                             scope = x.Key.Item3,
                             subject = x.Key.Item6,
+                            subjectId = x.Key.Item7,
                             period = x.Key.Item4,
+                            periodId = x.Key.Item5,
                             id = x.Key.Item1,
                             name = x.Key.Item2,
                             groups = classIds