dusenyao 3 年之前
父节点
当前提交
aa67e68687

+ 4 - 0
src/icons/svg/video-red.svg

@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M2 5C2 4.44771 2.44771 4 3 4H17C17.5523 4 18 4.44771 18 5V9.5L22 6.5V18L18 15V19C18 19.5523 17.5523 20 17 20H3C2.44771 20 2 19.5523 2 19V5Z" stroke="#FF6868" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M8.5 13C9.88071 13 11 11.8807 11 10.5C11 9.11929 9.88071 8 8.5 8C7.11929 8 6 9.11929 6 10.5C6 11.8807 7.11929 13 8.5 13Z" stroke="#FF6868" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

+ 1 - 0
src/router/index.js

@@ -103,6 +103,7 @@ const routes = [
   {
     path: '/task_detail',
     component: Layout,
+    meta: { title: '任务列表', link: '/' },
     children: [
       {
         path: '/task_detail/student/:id',

+ 27 - 2
src/views/main/TaskList.vue

@@ -35,11 +35,13 @@
           <div class="tasks-group-list">
             <div v-for="list in item.task_list" :key="list.id" class="tasks-group-list-info">
               <div class="tasks-group-list-info-name">
-                {{ timeType(list.time_type) }}任务:{{ list.name }}
+                <span @click="taskLink_outside(list.teaching_type, list.id)">
+                  {{ timeType(list.time_type) }}任务:{{ list.name }}
+                </span>
                 <el-link
                   class="task-link"
                   :underline="false"
-                  @click="taskLink(list.teaching_type, list.id)"
+                  @click.stop="taskLink(list.teaching_type, list.id)"
                 >
                   {{ teachingType(list.teaching_type) }}
                 </el-link>
@@ -122,6 +124,25 @@ export default {
         );
       }
     },
+
+    taskLink_outside(type, task_id) {
+      let userType = this.$store.state.user.user_type;
+      if (type === 10 && userType === 'TEACHER') {
+        CreateEnterLiveRoomSession({
+          task_id
+        }).then(({ live_room_sys_user_id, room_id, session_id, room_user_id }) => {
+          this.$router.push({
+            path: `/live/teacher`,
+            query: { live_room_sys_user_id, room_id, session_id, task_id, room_user_id }
+          });
+        });
+      } else {
+        this.$router.push(
+          `/task_detail/${userType === 'STUDENT' ? 'student' : 'teacher'}/${task_id}`
+        );
+      }
+    },
+
     dateSkip(num) {
       let day = 24 * 60 * 60 * 1000 * num;
       this.date = new Date(this.date.getTime() + day);
@@ -253,6 +274,10 @@ export default {
             }
 
             &-name {
+              > span {
+                cursor: pointer;
+              }
+
               .task-link {
                 font-size: 16px;
                 vertical-align: top;

+ 76 - 0
src/views/task_details/TaskTop.vue

@@ -0,0 +1,76 @@
+<template>
+  <div class="task-detail-top">
+    <div class="title">
+      <span class="title-name">{{ itemInfo.course_name }}</span>
+      <span class="title-time">{{ itemInfo.time_space_view_txt }}</span>
+    </div>
+    <div class="cs_item_name">{{ itemInfo.cs_item_name }}</div>
+    <div class="learning-material">
+      <div class="learning-material-title">学习资料</div>
+      <el-tag
+        v-for="item in itemInfo.cs_item_learning_material_list"
+        :key="item.file_id"
+        color="#fff"
+        :title="item.file_name"
+      >
+        <a :href="item.file_url" target="_blank">{{ item.file_name }}</a>
+      </el-tag>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    itemInfo: {
+      default: () => {
+        return {
+          course_name: '',
+          time_space_view_txt: '',
+          cs_item_name: '',
+          cs_item_learning_material_list: ''
+        };
+      },
+      type: Object
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.task-detail-top {
+  padding: 24px 32px;
+  background-color: #fff;
+  border-radius: 8px;
+
+  .title {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+
+    &-name {
+      font-size: 24px;
+      font-weight: 700;
+    }
+
+    &-time {
+      color: #737373;
+    }
+  }
+
+  .cs_item_name {
+    margin: 8px 0 24px;
+  }
+
+  .learning-material {
+    border-top: 1px solid #d9d9d9;
+    padding-top: 24px;
+    margin-bottom: 16px;
+
+    &-title {
+      font-size: 18px;
+      margin-bottom: 16px;
+    }
+  }
+}
+</style>

+ 238 - 117
src/views/task_details/student/index.vue

@@ -1,23 +1,7 @@
 <template>
-  <div class="task-detail">
-    <div class="task-detail-top">
-      <div class="title">
-        <span class="title-name">{{ course_name }}</span>
-        <span class="title-time">{{ time_space_view_txt }}</span>
-      </div>
-      <div class="cs_item_name">{{ cs_item_name }}</div>
-      <div class="learning-material">
-        <div class="learning-material-title">学习资料</div>
-        <el-tag
-          v-for="item in cs_item_learning_material_list"
-          :key="item.file_id"
-          color="#fff"
-          :title="item.file_name"
-        >
-          <a :href="item.file_url" target="_blank">{{ item.file_name }}</a>
-        </el-tag>
-      </div>
-    </div>
+  <div v-loading="loading" class="task-detail">
+    <task-top :item-info="itemInfo" />
+
     <div class="task-detail-main">
       <div class="time-type">{{ timeType }}任务 {{ name }}</div>
       <div class="time-interval">{{ time_space_view_txt }}</div>
@@ -29,9 +13,10 @@
           :key="item.courseware_id"
           color="#fff"
           :title="item.courseware_name"
-          @click="finishTask(item.courseware_id)"
+          @click="finishTask(item.courseware_id, item.is_finished)"
         >
           <svg-icon icon-class="courseware" /> <span>{{ item.courseware_name }}</span>
+          <svg-icon v-if="item.is_finished === 'true'" class="check-mark" icon-class="check-mark" />
         </el-tag>
       </div>
       <div class="accessory-list">
@@ -45,34 +30,95 @@
           <span>{{ item.file_name }}</span>
         </el-tag>
       </div>
-      <div class="submit-homework">
-        <span class="label">提交作业</span>
-        <el-upload action="no" :http-request="upload" multiple :show-file-list="false" accept="*">
-          <el-button><svg-icon icon-class="upload" /> 上传文件</el-button>
-        </el-upload>
-      </div>
-      <div class="file-list">
-        <el-tag
-          v-for="(item, i) in file_list"
-          :key="item.file_id"
-          color="#fff"
-          closable
-          :title="item.file_name"
-          @close="deleteFile(i)"
-        >
-          <span>{{ item.file_name }}</span>
-        </el-tag>
-      </div>
-      <div class="leave-message">
-        <span class="label">给教师留言</span>
-        <el-input v-model="student_message" type="textarea" resize="none" :rows="6"></el-input>
-      </div>
-      <div class="submit-button">
-        <el-button type="primary" @click="fillTaskExecuteInfo_Student">完成任务</el-button>
-      </div>
+      <!-- 完成评价 -->
+      <template v-if="my_execute_info.is_finished === 'true'">
+        <div class="teacher-commenting">
+          <div v-if="teaching_type === 10">
+            <span class="label">学员课后评价</span>
+            <el-input v-model="student_remark" disabled type="textarea" resize="none" :rows="6" />
+          </div>
+          <div v-if="teaching_type === 10">
+            <span class="label">学员课后评分</span>
+            <el-rate v-model="student_score" disabled />
+          </div>
+          <div>
+            <span class="label">给教师留言</span>
+            <el-input
+              v-model="my_execute_info.student_message"
+              disabled
+              type="textarea"
+              resize="none"
+              :rows="6"
+            />
+          </div>
+          <div>
+            <span class="label">教师点评</span>
+            <el-rate v-model="my_execute_info.teacher_score" disabled />
+            <span class="teacher_remark">{{ my_execute_info.teacher_remark }}</span>
+          </div>
+        </div>
+      </template>
+      <!-- 直播评价 -->
+      <template v-else-if="teaching_type === 10">
+        <div class="live-info">
+          <div>
+            <span class="enter-live" @click="enterLive">
+              <svg-icon icon-class="video-red" /> 点击进入直播间
+            </span>
+          </div>
+          <div>
+            <span class="label">学员课后评价</span>
+            <el-input v-model="student_remark" type="textarea" resize="none" :rows="6" />
+          </div>
+          <div>
+            <span class="label">学员课后评分</span>
+            <el-rate v-model="student_score" />
+          </div>
+          <div class="confirm">
+            <el-button type="primary" @click="fillTaskExecuteInfo_Student_live">提交</el-button>
+          </div>
+        </div>
+      </template>
+      <template v-else>
+        <div class="submit-homework">
+          <span class="label">提交作业</span>
+          <el-upload action="no" :http-request="upload" multiple :show-file-list="false" accept="*">
+            <el-button><svg-icon icon-class="upload" /> 上传文件</el-button>
+          </el-upload>
+        </div>
+        <div class="file-list">
+          <el-tag
+            v-for="(item, i) in file_list"
+            :key="item.file_id"
+            color="#fff"
+            closable
+            :title="item.file_name"
+            @close="deleteFile(i)"
+          >
+            <span>{{ item.file_name }}</span>
+          </el-tag>
+        </div>
+        <div class="leave-message">
+          <span class="label">给教师留言</span>
+          <el-input v-model="student_message" type="textarea" resize="none" :rows="6" />
+        </div>
+        <div class="submit-button">
+          <el-button type="primary" @click="fillTaskExecuteInfo_Student">完成任务</el-button>
+        </div>
+      </template>
     </div>
 
+    <completion-view
+      v-if="my_execute_info.is_finished === 'true'"
+      :task-id="id"
+      :cur-student-id="$store.state.user.user_code"
+      :cur-courseware-id="coursewareId"
+      :dialog-visible="dialogVisible_completion"
+      @dialogClose="dialogClose_completion"
+    />
+
     <finish-courseware
+      v-else
       :id="id"
       :courseware-id="coursewareId"
       :dialog-visible="dialogVisible"
@@ -82,33 +128,46 @@
 </template>
 
 <script>
+import TaskTop from '../TaskTop.vue';
 import FinishCourseware from '@/components/course/FinishCourseware.vue';
+import CompletionView from '@/components/course/CompletionView.vue';
 import { fileUpload, FileDownload } from '@/api/app';
+import { CreateEnterLiveRoomSession } from '@/api/live';
 import { GetTaskInfo, FillMyTaskExecuteInfo_Student } from '@/api/course';
 
 export default {
   components: {
-    FinishCourseware
+    FinishCourseware,
+    TaskTop,
+    CompletionView
   },
   data() {
     return {
       // 任务 ID
       id: this.$route.params.id,
+      itemInfo: {
+        course_name: '',
+        cs_item_name: '',
+        cs_item_learning_material_list: [],
+        time_space_view_txt: ''
+      },
       student_message: '',
       name: '',
       teaching_type: '',
       time_type: '',
-      course_name: '',
-      cs_item_name: '',
       content: '',
       task_mode: '',
       time_space_view_txt: '',
       courseware_list: [],
       accessory_list: [],
-      cs_item_learning_material_list: [],
       file_list: [],
       dialogVisible: false,
-      coursewareId: ''
+      coursewareId: '',
+      dialogVisible_completion: false,
+      my_execute_info: {},
+      student_remark: '',
+      student_score: 0,
+      loading: false
     };
   },
   computed: {
@@ -126,36 +185,51 @@ export default {
     }
   },
   created() {
+    this.loading = true;
     GetTaskInfo({
       id: this.id,
-      is_contain_cs_item_learning_material: true
-    }).then(
-      ({
-        name,
-        teaching_type,
-        time_type,
-        course_name,
-        cs_item_name,
-        courseware_list,
-        accessory_list,
-        cs_item_learning_material_list,
-        task_mode,
-        content,
-        time_space_view_txt
-      }) => {
-        this.name = name;
-        this.course_name = course_name;
-        this.cs_item_name = cs_item_name;
-        this.content = content;
-        this.teaching_type = teaching_type;
-        this.time_type = time_type;
-        this.courseware_list = courseware_list;
-        this.accessory_list = accessory_list;
-        this.task_mode = task_mode;
-        this.cs_item_learning_material_list = cs_item_learning_material_list;
-        this.time_space_view_txt = time_space_view_txt;
-      }
-    );
+      is_contain_cs_item_learning_material: true,
+      is_contain_my_execute_info: true
+    })
+      .then(
+        ({
+          name,
+          teaching_type,
+          time_type,
+          course_name,
+          cs_item_name,
+          courseware_list,
+          accessory_list,
+          cs_item_learning_material_list,
+          task_mode,
+          content,
+          time_space_view_txt,
+          my_execute_info,
+          student_remark,
+          student_score
+        }) => {
+          this.itemInfo = {
+            time_space_view_txt,
+            course_name,
+            cs_item_name,
+            cs_item_learning_material_list
+          };
+          this.student_remark = student_remark;
+          this.student_score = student_score;
+          this.name = name;
+          this.content = content;
+          this.teaching_type = teaching_type;
+          this.time_type = time_type;
+          this.courseware_list = courseware_list;
+          this.accessory_list = accessory_list;
+          this.task_mode = task_mode;
+          this.time_space_view_txt = time_space_view_txt;
+          this.my_execute_info = my_execute_info;
+        }
+      )
+      .finally(() => {
+        this.loading = false;
+      });
   },
   methods: {
     upload(file) {
@@ -189,17 +263,54 @@ export default {
         is_finished: true
       }).then(() => {
         this.$message.success('任务完成成功');
+        this.$router.go(0);
+      });
+    },
+
+    fillTaskExecuteInfo_Student_live() {
+      FillMyTaskExecuteInfo_Student({
+        task_id: this.id,
+        is_finished: true,
+        student_remark: this.student_remark,
+        student_score: this.student_score
+      }).then(() => {
+        this.$message.success('提交成功');
+        this.$router.go(0);
+      });
+    },
+
+    enterLive() {
+      CreateEnterLiveRoomSession({
+        task_id: this.id
+      }).then(({ live_room_sys_user_id, room_id, session_id, room_user_id }) => {
+        this.$router.push({
+          path: `/live/student}`,
+          query: { live_room_sys_user_id, room_id, session_id, task_id: this.id, room_user_id }
+        });
       });
     },
 
     // 完成任务
-    finishTask(id) {
+    finishTask(id, is_finished) {
+      if (this.my_execute_info.is_finished === 'true' && is_finished === 'false') {
+        return this.$message.warning('该课件没有被完成');
+      }
       this.coursewareId = id;
-      this.dialogVisible = true;
+      if (this.my_execute_info.is_finished === 'true') {
+        this.dialogVisible_completion = true;
+      } else {
+        this.dialogVisible = true;
+      }
     },
+
     dialogClose() {
       this.dialogVisible = false;
       this.coursewareId = '';
+    },
+
+    dialogClose_completion() {
+      this.dialogVisible_completion = false;
+      this.coursewareId = '';
     }
   }
 };
@@ -212,6 +323,9 @@ $bor-color: #d9d9d9;
 .task-detail {
   @include container;
 
+  margin-top: 56px;
+  min-height: calc(100vh - 130px);
+
   .el-tag {
     @include el-tag;
 
@@ -220,42 +334,6 @@ $bor-color: #d9d9d9;
     border-color: $bor-color;
   }
 
-  &-top {
-    padding: 24px 32px;
-    background-color: #fff;
-    border-radius: 8px;
-
-    .title {
-      display: flex;
-      justify-content: space-between;
-      align-items: center;
-
-      &-name {
-        font-size: 24px;
-        font-weight: 700;
-      }
-
-      &-time {
-        color: #737373;
-      }
-    }
-
-    .cs_item_name {
-      margin: 8px 0 24px;
-    }
-
-    .learning-material {
-      border-top: 1px solid $bor-color;
-      padding-top: 24px;
-      margin-bottom: 16px;
-
-      &-title {
-        font-size: 18px;
-        margin-bottom: 16px;
-      }
-    }
-  }
-
   &-main {
     background-color: #fff;
     border-radius: 8px;
@@ -279,6 +357,41 @@ $bor-color: #d9d9d9;
       align-items: center;
     }
 
+    .teacher-commenting {
+      @extend .submit-homework;
+
+      flex-direction: column;
+
+      > div {
+        display: flex;
+        width: 100%;
+
+        & + div {
+          margin-top: 24px;
+        }
+
+        .teacher_remark {
+          margin-left: 24px;
+        }
+      }
+    }
+
+    .live-info {
+      @extend .teacher-commenting;
+
+      .enter-live {
+        cursor: pointer;
+        padding: 8px 26px;
+        color: #ff6868;
+        border: 1px solid #ff6868;
+        border-radius: 20px;
+      }
+
+      .confirm {
+        padding-left: 105px;
+      }
+    }
+
     .file-list {
       padding-left: 105px;
       margin-bottom: 16px;
@@ -310,6 +423,13 @@ $bor-color: #d9d9d9;
         font-size: 18px;
         margin-right: 8px;
       }
+
+      .check-mark {
+        margin-left: 12px;
+        top: 2px;
+        right: -20px;
+        position: relative;
+      }
     }
 
     .task-require,
@@ -321,7 +441,8 @@ $bor-color: #d9d9d9;
 
       .label {
         display: inline-block;
-        width: 105px;
+        width: 120px;
+        min-width: 120px;
       }
     }
 

+ 19 - 61
src/views/task_details/teacher/index.vue

@@ -1,23 +1,7 @@
 <template>
   <div class="teacher-task-detail">
-    <div class="teacher-task-detail-top">
-      <div class="title">
-        <span class="title-name">{{ course_name }}</span>
-        <span class="title-time">{{ time_space_view_txt }}</span>
-      </div>
-      <div class="course_name">{{ cs_item_name }}</div>
-      <div class="learning-material">
-        <div class="learning-material-title">学习资料</div>
-        <el-tag
-          v-for="item in cs_item_learning_material_list"
-          :key="item.file_id"
-          color="#fff"
-          :title="item.file_name"
-        >
-          <a :href="item.file_url" target="_blank">{{ item.file_name }}</a>
-        </el-tag>
-      </div>
-    </div>
+    <task-top :item-info="itemInfo" />
+
     <div class="teacher-task-detail-main">
       <div class="student-finish-situation">
         <div>学员完成情况</div>
@@ -110,6 +94,7 @@
 
 <script>
 import CompletionView from '@/components/course/CompletionView.vue';
+import TaskTop from '../TaskTop.vue';
 import {
   GetTaskInfo,
   GetTaskStudentExecuteInfo,
@@ -117,20 +102,23 @@ import {
 } from '@/api/course';
 
 export default {
-  components: { CompletionView },
+  components: { CompletionView, TaskTop },
   data() {
     return {
       id: this.$route.params.id,
       name: '',
       teaching_type: '',
+      itemInfo: {
+        course_name: '',
+        cs_item_name: '',
+        cs_item_learning_material_list: [],
+        time_space_view_txt: ''
+      },
       time_type: '',
-      course_name: '',
-      cs_item_name: '',
       task_mode: '',
       time_space_view_txt: '',
       courseware_list: [],
       accessory_list: [],
-      cs_item_learning_material_list: [],
       file_list: [],
       student_list: [],
       curStudentId: '',
@@ -168,15 +156,18 @@ export default {
         time_space_view_txt,
         student_list
       }) => {
+        this.itemInfo = {
+          time_space_view_txt,
+          course_name,
+          cs_item_name,
+          cs_item_learning_material_list
+        };
         this.name = name;
-        this.course_name = course_name;
-        this.cs_item_name = cs_item_name;
         this.teaching_type = teaching_type;
         this.time_type = time_type;
         this.courseware_list = courseware_list;
         this.accessory_list = accessory_list;
         this.task_mode = task_mode;
-        this.cs_item_learning_material_list = cs_item_learning_material_list;
         this.time_space_view_txt = time_space_view_txt;
         this.student_list = student_list;
         if (student_list.length > 0) this.getTaskStudentExecuteInfo(student_list[0].student_id);
@@ -261,6 +252,9 @@ $bor-color: #d9d9d9;
   @include container;
   @include dialog;
 
+  margin-top: 56px;
+  min-height: calc(100vh - 130px);
+
   .el-tag {
     @include el-tag;
 
@@ -268,42 +262,6 @@ $bor-color: #d9d9d9;
     margin-right: 8px;
     border-color: $bor-color;
   }
-  // 课程信息
-  &-top {
-    padding: 24px 32px;
-    background-color: #fff;
-    border-radius: 8px;
-
-    .title {
-      display: flex;
-      justify-content: space-between;
-      align-items: center;
-
-      &-name {
-        font-size: 24px;
-        font-weight: 700;
-      }
-
-      &-time {
-        color: #737373;
-      }
-    }
-
-    .course_name {
-      margin: 8px 0 24px;
-    }
-
-    .learning-material {
-      border-top: 1px solid $bor-color;
-      padding-top: 24px;
-      margin-bottom: 16px;
-
-      &-title {
-        font-size: 18px;
-        margin-bottom: 16px;
-      }
-    }
-  }
 
   &-main {
     display: flex;