123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707 |
- <template>
- <div v-loading="loading" class="teacher-task-detail">
- <TaskTop :item-info="itemInfo" :is-exercises="isExercises" type="teacher" @viewFile="showFileVisible" />
- <div class="teacher-task-detail-main">
- <div class="student-finish-situation">
- <div>{{ $t('Key308') }}</div>
- <div class="student-list" :style="{ height: student_list_height + 'px' }">
- <ul>
- <li
- v-for="item in student_list"
- :key="item.student_id"
- :class="['student-item', { active: item.student_id === curStudentId }]"
- @click="getTaskStudentExecuteInfo(item.student_id)"
- >
- <span>{{ item.student_name }}</span>
- <svg-icon v-if="!isExercises && item.is_finished === 'true'" icon-class="check-mark" />
- <span v-if="isExercises && item.exercise_info.is_finish === 'true'" class="submitted">已提交</span>
- </li>
- </ul>
- </div>
- </div>
- <div class="finish-detail">
- <template v-if="isExercises">
- <div v-if="exercise_info.answer_record?.is_finish === 'true'" ref="situation" class="exercise">
- <div class="title">测试报告</div>
- <div class="color-list">
- <div v-for="{ label, color } in questionColorList" :key="label" class="color-item">
- <span class="color" :style="{ backgroundColor: color }"></span>
- <span>{{ label }}</span>
- </div>
- </div>
- <div class="exercise-details">
- <div class="info-item">
- <span class="label">完成时间</span>
- <span class="exercise-info">{{ exercise_info.answer_record?.finish_time }}</span>
- </div>
- <div class="info-item">
- <span class="label">耗时</span>
- <span class="exercise-info">{{
- secondFormatConversion(exercise_info.answer_record?.answer_duration, 'chinese')
- }}</span>
- </div>
- <div class="info-item">
- <span class="label">正确</span>
- <span class="exercise-info">{{ exercise_info.answer_record?.right_count }}</span>
- </div>
- <div class="info-item">
- <span class="label">错误</span>
- <span class="exercise-info">{{ exercise_info.answer_record?.error_count }}</span>
- </div>
- <div class="info-item">
- <span class="label">正确率</span>
- <span class="exercise-info">{{ exercise_info.answer_record?.right_percent }}%</span>
- </div>
- </div>
- <!-- 问题列表 -->
- <div class="question-list">
- <span
- v-for="({ question_id, color_mark = '' }, i) in exercise_info.question_list"
- :key="question_id"
- :class="['question-list-item']"
- :style="{
- backgroundColor: color_mark,
- color: [questionColorList[0].color, questionColorList[1].color, questionColorList[2].color].includes(
- color_mark.toUpperCase()
- )
- ? '#fff'
- : '#2c2c2c'
- }"
- @click="
- exerciseLink(
- exercise_info.answer_record.exercise_share_record_id,
- exercise_info.answer_record.exercise_answer_record_id,
- exercise_info.answer_record.exercise_id,
- i
- )
- "
- >
- {{ i + 1 }}
- </span>
- </div>
- <div class="total-score">
- <div>总得分</div>
- <div>{{ exercise_info.answer_record?.total_score }}</div>
- </div>
- <div class="footer">
- <el-button type="primary" @click="remarkTaskStudentExecuteInfo_Teacher">批改完成</el-button>
- <el-button @click="resendStudentExerciseTask">重发</el-button>
- <el-button v-if="student_list.length > 1" @click="next">
- {{ buttonName }} <i :class="buttonIcon"></i>
- </el-button>
- </div>
- </div>
- <div v-else ref="situation" class="exercise">
- <div>练习任务</div>
- <div class="exercise-task">
- <el-tag color="#fff">
- <div class="courseware">
- <svg-icon icon-class="courseware" />
- <span class="courseware_name nowrap-ellipsis">{{ exercise_info.exercise_name }}</span>
- </div>
- </el-tag>
- <span class="not-submitted">未提交</span>
- </div>
- <div class="footer">
- <el-button @click="resendStudentExerciseTask">重发</el-button>
- <el-button v-if="student_list.length > 1" @click="next">
- {{ buttonName }} <i :class="buttonIcon"></i>
- </el-button>
- </div>
- </div>
- </template>
- <template v-else>
- <div class="student-info">
- <div>
- <el-avatar :src="curFinishDetail.student_image_url" :size="32" icon="el-icon-user-solid" />
- <span class="student-info-name">{{ curFinishDetail.student_name }}</span>
- </div>
- <span class="finish-time">{{ curFinishDetail.finish_time_view_txt }}</span>
- </div>
- <div ref="situation" class="finish-situation">
- <template v-if="curFinishDetail.courseware_list.length > 0">
- <div class="title">
- {{ $t('Key312') }}
- </div>
- <div class="courseware-list">
- <el-tag
- v-for="item in curFinishDetail.courseware_list"
- :key="item.courseware_id"
- color="#fff"
- :title="item.courseware_name"
- @click="showCompletionView(item.courseware_id, item.is_finished, item.group_id_selected_info)"
- >
- <div class="courseware">
- <svg-icon icon-class="courseware" />
- <span class="courseware_name nowrap-ellipsis">{{ item.courseware_name }}</span>
- <svg-icon v-if="item.is_finished === 'true'" class="check-mark" icon-class="check-mark-circle" />
- </div>
- </el-tag>
- </div>
- </template>
- <template v-if="accessory_list.length > 0">
- <div class="title">
- {{ $t('Key313') }}
- </div>
- <div>
- <el-tag v-for="item in accessory_list" :key="item.file_id" color="#fff" :title="item.file_name">
- <span @click="showFileVisible(item.file_name, item.file_id)">{{ item.file_name }}</span>
- </el-tag>
- </div>
- </template>
- <!-- 作业列表 -->
- <template v-if="is_enable_homework && curFinishDetail.homework_list.length > 0">
- <div class="title">
- {{ $t('Key314') }}
- </div>
- <div>
- <el-tag
- v-for="item in curFinishDetail.homework_list"
- :key="item.file_id"
- color="#fff"
- :title="item.file_name"
- >
- <span @click="showFileVisible(item.file_name, item.file_id)">{{ item.file_name }}</span>
- </el-tag>
- </div>
- </template>
- <!-- 学员留言 -->
- <template v-if="is_enable_message && curFinishDetail.student_message">
- <div class="title">
- {{ $t('Key315') }}
- </div>
- <div>{{ curFinishDetail.student_message }}</div>
- </template>
- <template v-if="teachingType === 10 && is_enable_KHPJ">
- <div class="title">
- {{ $t('Key316') }}
- </div>
- <div>{{ student_remark }}</div>
- <div class="title">
- <span>{{ $t('Key317') }}</span>
- <el-rate v-model="student_score" disabled />
- </div>
- </template>
- <div class="title">
- <span>{{ $t('Key318') }}</span>
- <el-rate v-model="teacher_score" />
- </div>
- <div>
- <el-input v-model="teacher_remark" type="textarea" resize="none" :rows="6" maxlength="3000" />
- </div>
- <div class="confirm">
- <el-button type="primary" @click="remarkTaskStudentExecuteInfo_Teacher">
- {{ $t('Key319') }}
- </el-button>
- <el-button v-if="student_list.length > 1" @click="next">
- {{ buttonName }} <i class="el-icon-right"></i>
- </el-button>
- </div>
- </div>
- </template>
- </div>
- </div>
- <CompletionView
- :task-id="id"
- :cur-student-id="curStudentId"
- :cur-courseware-id="curCoursewareId"
- :dialog-visible="dialogVisible"
- :preview-group-id="previewGroupId"
- @dialogClose="dialogClose"
- />
- <ShowFile :visible="visible" :file-name="curFileName" :file-id="curFileId" @close="dialogShowFileClose" />
- </div>
- </template>
- <script>
- export default {
- name: 'TaskDetailsTeacher'
- };
- </script>
- <script setup>
- import { ref, inject, nextTick, computed } from 'vue';
- import {
- GetTaskInfo,
- GetTaskStudentExecuteInfo,
- RemarkTaskStudentExecuteInfo_Teacher,
- ResendStudentExerciseTask
- } from '@/api/course';
- import { useRoute } from 'vue-router/composables';
- import { Message } from 'element-ui';
- import { useShowFile } from '@/common/show_file/index';
- import { useExerciseTeacher, questionColorList } from './exercise';
- import { secondFormatConversion } from '@/utils';
- import CompletionView from '@/components/course/CompletionView.vue';
- import ShowFile from '@/common/show_file/index.vue';
- import TaskTop from '../TaskTop.vue';
- const $t = inject('$t');
- const route = useRoute();
- let id = route.params.id;
- const { exerciseLink } = useExerciseTeacher();
- // 任务详情
- let itemInfo = ref({});
- let teachingType = ref('');
- let isExercises = computed(() => {
- return teachingType.value === 15;
- });
- let accessory_list = ref([]);
- let student_list = ref([]);
- let loading = ref(true);
- // 开启课后评价
- let is_enable_KHPJ = ref(false);
- let is_enable_homework = ref(false);
- let is_enable_message = ref(false);
- GetTaskInfo({
- id,
- is_contain_cs_item_learning_material: true,
- is_contain_student: true
- })
- .then(
- ({
- name,
- teaching_type,
- course_name,
- courseware_list,
- cs_item_name,
- accessory_list: accList,
- cs_item_learning_material_list,
- time_space_view_txt,
- student_list: stuList,
- is_enable_KHPJ: isKHPJ,
- is_enable_homework: isHomework,
- is_enable_message: isMessage,
- content,
- cs_item_begin_time,
- cs_item_end_time,
- finish_status
- }) => {
- itemInfo.value = {
- name,
- time_space_view_txt,
- course_name,
- cs_item_name,
- cs_item_learning_material_list,
- courseware_list,
- content,
- cs_item_time: `${cs_item_begin_time} ~ ${cs_item_end_time}`,
- finish_status
- };
- teachingType.value = teaching_type;
- accessory_list.value = accList;
- is_enable_KHPJ.value = isKHPJ === 'true';
- is_enable_homework.value = isHomework === 'true';
- is_enable_message.value = isMessage === 'true';
- student_list.value = stuList;
- if (student_list.value.length > 0) getTaskStudentExecuteInfo(student_list.value[0].student_id);
- }
- )
- .finally(() => {
- loading.value = false;
- });
- const situation = ref();
- // 当前学生完成详情
- let curFinishDetail = ref({
- student_name: '',
- student_image_url: '',
- courseware_list: [],
- homework_list: [],
- student_message: '',
- finish_time_view_txt: ''
- });
- let curStudentId = ref('');
- let teacher_remark = ref('');
- let teacher_score = ref(0);
- let student_remark = ref('');
- let student_score = ref(0);
- let student_list_height = ref(490);
- let exercise_info = ref({}); // 练习题信息
- function getTaskStudentExecuteInfo(student_id) {
- GetTaskStudentExecuteInfo({
- task_id: id,
- student_id
- }).then(
- ({
- courseware_list,
- homework_list,
- student_message,
- student_name,
- student_image_url,
- finish_time_view_txt,
- teacher_remark: tRemake,
- teacher_score: tScore,
- student_remark: sRemake,
- student_score: stuScore,
- exercise_info: exerciseInfo
- }) => {
- curStudentId.value = student_id;
- teacher_remark.value = tRemake;
- teacher_score.value = tScore;
- student_remark.value = sRemake;
- student_score.value = stuScore;
- curFinishDetail.value = {
- courseware_list,
- homework_list,
- student_message,
- student_name,
- student_image_url,
- finish_time_view_txt
- };
- exercise_info.value = exerciseInfo;
- nextTick(() => {
- student_list_height.value = situation.value.clientHeight;
- });
- }
- );
- }
- // 重发学员练习任务
- function resendStudentExerciseTask() {
- ResendStudentExerciseTask({ task_id: id, student_id: curStudentId.value }).then(() => {
- Message.success('重发成功');
- getTaskStudentExecuteInfo(curStudentId.value);
- student_list.value.find(({ student_id }) => student_id === curStudentId.value).exercise_info.is_finish = 'false';
- });
- }
- let previewGroupId = ref('[]');
- let dialogVisible = ref(false);
- let curCoursewareId = ref('');
- function showCompletionView(id, is_finished, group_id_selected_info) {
- if (is_finished === 'false') return Message.warning($t('Key338'));
- previewGroupId.value = group_id_selected_info.length <= 0 ? '[]' : group_id_selected_info;
- curCoursewareId.value = id;
- dialogVisible.value = true;
- }
- function dialogClose() {
- curCoursewareId.value = '';
- dialogVisible.value = false;
- }
- let { visible, curFileId, curFileName, dialogShowFileClose, showFileVisible } = useShowFile();
- function remarkTaskStudentExecuteInfo_Teacher() {
- RemarkTaskStudentExecuteInfo_Teacher({
- task_id: id,
- student_id: curStudentId.value,
- teacher_score: teacher_score.value,
- teacher_remark: teacher_remark.value
- }).then(() => {
- Message.success(isExercises.value ? '批改成功' : $t('Key324'));
- });
- }
- let buttonName = computed(() => {
- const list = student_list.value;
- if (list.length <= 0) return '';
- return list[list.length - 1].student_id === curStudentId.value ? $t('Key618') : $t('Key619');
- });
- let buttonIcon = computed(() => {
- const list = student_list.value;
- if (list.length <= 0) return '';
- return list[list.length - 1].student_id === curStudentId.value ? 'el-icon-back' : 'el-icon-right';
- });
- function next() {
- const list = student_list.value;
- if (list.length <= 0) return Message.warning($t('Key325'));
- const curIndex = list.findIndex(({ student_id }) => student_id === curStudentId.value);
- const nextStudentId = (list.length - 1 === curIndex ? list[curIndex - 1] : list[curIndex + 1]).student_id;
- if (nextStudentId) getTaskStudentExecuteInfo(nextStudentId);
- }
- </script>
- <style lang="scss">
- @import '~@/styles/mixin';
- $bor-color: #d9d9d9;
- .teacher-task-detail {
- @include container;
- @include dialog;
- min-height: calc(100vh - 130px);
- .el-tag {
- @include el-tag;
- margin: 0 8px 6px 0;
- border-color: $bor-color;
- border-radius: 4px;
- > span {
- cursor: pointer;
- }
- }
- &-main {
- display: flex;
- min-height: calc(100vh - 390px);
- margin-top: 16px;
- background-color: #fff;
- border-radius: 8px;
- .student-finish-situation {
- flex: 3;
- padding: 24px 0;
- > div:first-child {
- padding: 0 32px;
- margin-bottom: 24px;
- font-weight: 700;
- }
- // 学员列表
- .student-list {
- overflow: auto;
- ul {
- cursor: pointer;
- .student-item {
- display: flex;
- justify-content: space-between;
- padding: 8px 32px;
- &.active {
- background-color: #f2f2f2;
- }
- .submitted {
- position: relative;
- left: 16px;
- color: #00c264;
- }
- }
- }
- }
- }
- // 完成详情
- .finish-detail {
- flex: 7;
- border-left: 1px solid #dbdbdb;
- // 练习题
- .exercise {
- display: flex;
- flex-direction: column;
- row-gap: 24px;
- padding: 24px 40px;
- .color-list {
- display: flex;
- column-gap: 24px;
- .color-item {
- display: flex;
- column-gap: 8px;
- align-items: center;
- .color {
- width: 16px;
- height: 16px;
- border-radius: 50%;
- }
- }
- }
- // 练习题详情
- .exercise-details {
- display: flex;
- column-gap: 80px;
- padding: 16px 40px;
- background-color: #f7f7f7;
- .info-item {
- display: flex;
- flex-direction: column;
- row-gap: 12px;
- .label {
- font-size: 14px;
- color: #949494;
- white-space: nowrap;
- }
- .exercise-info {
- font-size: 20px;
- font-weight: bold;
- color: #333;
- }
- }
- }
- // 题目列表
- .question-list {
- display: flex;
- flex-wrap: wrap;
- gap: 24px;
- width: 770px;
- margin-bottom: 40px;
- &-item {
- width: 56px;
- height: 40px;
- padding: 8px;
- line-height: 24px;
- text-align: center;
- cursor: pointer;
- background-color: #f0f0f0;
- border-radius: 20px;
- }
- }
- .total-score {
- display: flex;
- flex-direction: column;
- row-gap: 8px;
- font-size: 14px;
- :first-child {
- color: #949494;
- }
- :last-child {
- font-weight: bold;
- color: #333;
- }
- }
- &-task {
- display: flex;
- column-gap: 16px;
- align-items: center;
- .el-tag {
- .courseware {
- display: flex;
- column-gap: 12px;
- align-items: center;
- .svg-icon {
- font-size: 18px;
- }
- &_name {
- display: inline-block;
- max-width: 120px;
- font-size: 16px;
- }
- }
- }
- .not-submitted {
- color: #e43e3e;
- }
- }
- .footer {
- .el-button {
- font-weight: bold;
- }
- }
- }
- .student-info {
- display: flex;
- justify-content: space-between;
- height: 89px;
- padding: 28px 32px;
- line-height: 32px;
- border-bottom: 1px solid #dbdbdb;
- &-name {
- display: inline-block;
- height: 32px;
- margin-left: 24px;
- line-height: 32px;
- vertical-align: text-bottom;
- }
- .finish-time {
- color: #999;
- }
- }
- // 完成情况
- .finish-situation {
- width: 100%;
- padding: 24px 32px;
- .el-rate {
- display: inline-block;
- margin-left: 42px;
- }
- .title {
- font-size: 20px;
- font-weight: 500;
- line-height: 30px; /* 150% */
- color: #2c2c2c;
- + div {
- padding: 16px 0;
- font-size: 16px;
- font-weight: 400;
- line-height: 24px; /* 150% */
- color: #2c2c2c;
- opacity: 0.6;
- }
- }
- .courseware-list {
- .el-tag {
- cursor: pointer;
- .courseware {
- overflow: hidden;
- .svg-icon {
- margin-right: 12px;
- font-size: 18px;
- vertical-align: super;
- }
- .check-mark {
- position: relative;
- margin: 0 0 0 12px;
- }
- &_name {
- display: inline-block;
- max-width: 120px;
- }
- }
- }
- }
- // 学员详情按钮
- .confirm {
- display: flex;
- justify-content: space-between;
- .el-button {
- width: 110px;
- }
- }
- }
- }
- }
- }
- </style>
|