提交 468e4f08 authored 作者: 王鹏飞's avatar 王鹏飞

chore: update

上级 d669985a
......@@ -5,7 +5,7 @@ const emit = defineEmits<{
(e: 'resize'): void
}>()
defineProps<{ isLeftShow?: number }>()
defineProps<{ isLeftShow?: boolean }>()
const leftPanelVisible = $ref<boolean>(true)
const leftPanelWidth = useStorage('leftPanelWidth', 400)
......@@ -42,7 +42,7 @@ onMounted(() => {
<template>
<section class="drag-panel">
<div v-show="isLeftShow !== 1" class="drag-panel-left" :class="{ 'is-hidden': !leftPanelVisible }">
<div v-show="!isLeftShow" class="drag-panel-left" :class="{ 'is-hidden': !leftPanelVisible }">
<div class="drag-cover" v-if="dragFlag"></div>
<slot name="left"></slot>
<div class="panel-resize" id="panel-resize"></div>
......@@ -73,6 +73,7 @@ onMounted(() => {
.drag-panel {
display: flex;
height: calc(100vh - 110px);
gap: 20px;
}
.drag-panel-left {
position: relative;
......@@ -123,7 +124,6 @@ onMounted(() => {
display: flex;
flex-direction: column;
height: 100%;
margin-left: 20px;
}
.drag-cover {
width: 100%;
......
......@@ -35,7 +35,7 @@ const title = computed(() => {
// 列表配置
const listOptions = computed(() => {
let columns = []
let columns: any = []
switch (props.row.type) {
case 6:
// 用户标签
......
......@@ -30,7 +30,12 @@ export function getExperimentVideoPlayInfo(params: { source_id: string }) {
}
// 获取实验讨论交流
export function getExperimentDiscussList(params: { experiment_id: string; tag: number; page?: number; 'per-page'?: number }) {
export function getExperimentDiscussList(params: {
experiment_id: string
tag: number
page?: number
'per-page'?: number
}) {
return httpRequest.get('/api/lab/v1/student/experiment-topic/list', { params })
}
// 发表新话题
......@@ -85,11 +90,21 @@ export function getExperimentReportTemplate(params: { experiment_id: string }) {
return httpRequest.get('/api/lab/v1/student/experiment/report-template', { params })
}
// 更新实验在线报告
export function updateExperimentReport(data: { experiment_id: string; experiment_address: string; experiment_date: string; detail: string }) {
export function updateExperimentReport(data: {
experiment_id: string
experiment_address: string
experiment_date: string
detail: string
}) {
return httpRequest.post('/api/lab/v1/student/experiment/upload-online-report', data)
}
// 缓存实验在线报告
export function cacheExperimentReport(data: { experiment_id: string; experiment_address: string; experiment_date: string; detail: string }) {
export function cacheExperimentReport(data: {
experiment_id: string
experiment_address: string
experiment_date: string
detail: string
}) {
return httpRequest.post('/api/lab/v1/student/experiment/cache-online-report', data)
}
// 获取实验在线报告缓存
......@@ -120,3 +135,8 @@ export function getExperimentQuestion(params: { experiment_id: string; id: strin
export function getExperimentExamList(params: { experiment_id: string }) {
return httpRequest.get('/api/lab/v1/student/experiment-exam/exams', { params })
}
// 学生查看分数详情页面
export function getExperimentScoreDetail(params: { experiment_id: string; type: string }) {
return httpRequest.get('/api/lab/v1/student/experiment-question/score-detail', { params })
}
......@@ -12,12 +12,16 @@ interface Props {
course_id?: string
}
const props = defineProps<Props>()
const emits = defineEmits(['empty'])
let list = $ref<ExperimentBookType[]>([])
function fetchInfo() {
if (!props.experiment_id) return
getExperimentBookList({ experiment_id: props.experiment_id }).then(res => {
getExperimentBookList({ experiment_id: props.experiment_id }).then((res) => {
list = res.data.items
if (list.length === 0) {
emits('empty')
}
})
}
watchEffect(() => {
......@@ -34,7 +38,7 @@ function handleView(row: ExperimentBookType) {
log.upload({
event: 'file_event',
action: 'experiment_book_stu_watch_action',
data: { experiment_id: props.experiment_id, course_id: props.course_id, book_id: row.id }
data: { experiment_id: props.experiment_id, course_id: props.course_id, book_id: row.id },
})
}
// 关闭
......
......@@ -8,12 +8,16 @@ interface Props {
course_id?: string
}
const props = defineProps<Props>()
const emits = defineEmits(['empty'])
let detail = $ref<ExperimentBookType>()
function fetchInfo() {
if (!props.experiment_id) return
getExperimentCase({ experiment_id: props.experiment_id }).then(res => {
detail = res.data.detail
getExperimentCase({ experiment_id: props.experiment_id }).then((res) => {
detail = res.data.detail || {}
if (detail && Object.keys(detail).length === 0) {
emits('empty')
}
})
}
watchEffect(() => {
......
......@@ -10,6 +10,7 @@ interface Props {
}
const props = defineProps<Props>()
const model = defineModel()
const emits = defineEmits(['empty'])
const cookies = useCookies()
......@@ -22,22 +23,27 @@ const currentExam = computed(() => {
// 考试平台 URL
const examURL = computed(() => {
if (!currentExam.value) return ''
return appConfig.system !== 'x' || props.examStatus !== 0
? `${import.meta.env.VITE_EXAM_SHOW_URL}/exam/${currentExam.value?.exam_id}`
: `${import.meta.env.VITE_EXAM_SHOW_URL}/exam/${
return appConfig.system === 'x' && props.examStatus === 0
? `${import.meta.env.VITE_EXAM_SHOW_URL}/exam/${
currentExam.value?.exam_id
}?has_time=0&has_submit=0&has_save=1&show_answer=1`
: `${import.meta.env.VITE_EXAM_SHOW_URL}/exam/${currentExam.value?.exam_id}`
// return `https://dev.ezijing.com:5173/exam/7003551966412406784?has_time=0&has_submit=0&has_save=1&show_answer=1`
})
async function fetchInfo() {
if (!props.experiment_id) return
const res = await getExperimentExamList({ experiment_id: props.experiment_id })
const resCookies = res.data.cookies
cookies.set(resCookies.key, resCookies.auth_key, { domain: '.ezijing.com', path: '/' })
list.value = res.data.items || []
model.value = examURL.value
if (list.value.length === 0) {
emits('empty')
}
}
onMounted(() => {
watchEffect(() => {
fetchInfo()
})
</script>
......@@ -50,11 +56,9 @@ onMounted(() => {
>{{ currentExam.exam_info.start_time }}{{ currentExam.exam_info.end_time }}</el-form-item
>
</el-form>
<div style="width: 100%; height: 100%" v-if="props.examStatus === 0">
<div style="width: 100%; height: 100%">
<iframe style="width: 100%; height: 100%" allowfullscreen class="iframe" :src="examURL" frameborder="0"></iframe>
</div>
<!-- <teleport to=".lab-box"> -->
<!-- </teleport> -->
</template>
<el-empty description="暂无数据" v-else />
</template>
......@@ -4,7 +4,7 @@ import { Document } from '@element-plus/icons-vue'
import { filesize } from 'filesize'
interface Props {
experiment_id: string,
experiment_id: string
exam_status?: number
}
interface QuestionListItem {
......@@ -20,6 +20,7 @@ interface QuestionGroupList {
}
const props = defineProps<Props>()
const emits = defineEmits(['empty'])
const questionIndex = ref<number>(1)
const questionId = computed(() => {
......@@ -45,6 +46,9 @@ async function fetchList() {
if (!props.experiment_id) return
const res = await getExperimentQuestionList({ experiment_id: props.experiment_id })
questionList.value = res.data.items
if (questionList.value.length === 0) {
emits('empty')
}
}
watchEffect(() => {
if (props.experiment_id) fetchList()
......@@ -52,19 +56,21 @@ watchEffect(() => {
// 试题详情
const questionDetail = ref()
const file = ref()
async function fetchDetail() {
if (!questionId.value) return
const res = await getExperimentQuestion({ experiment_id: props.experiment_id, id: questionId.value })
const detail = res.data.detail
let files = []
const detail = res.data.detail || {}
let answer: any = {}
try {
files = JSON.parse(detail.files)
answer = JSON.parse(detail.answer)
file.value = answer.data?.file || {}
} catch (error) {
console.log(error)
}
questionDetail.value = { ...detail, files, score: parseFloat(detail.score) }
questionDetail.value = { ...detail, answer, score: parseFloat(detail.score) }
}
watch(questionId, id => {
watch(questionId, (id) => {
if (id) fetchDetail()
})
......@@ -79,7 +85,9 @@ function handleNext() {
}
function getQuestionTypeName(type: string) {
if (['101', '102'].includes(type)) return '用户/事件管理'
if (['101'].includes(type)) return '用户管理'
if (['102'].includes(type)) return '事件管理'
// if (['101', '102'].includes(type)) return '用户/事件管理'
if (['201', '202'].includes(type)) return '标签管理'
if (['301', '302'].includes(type)) return '群组管理'
if (['401', '402', '403', '404', '405', '406', '407'].includes(type)) return '营销资料管理'
......@@ -111,17 +119,18 @@ function customFloor(num: number) {
<el-card shadow="never" class="question-item" v-if="questionDetail">
<h3 class="question-item__title">{{ getQuestionTypeName(questionDetail.type) }}</h3>
<p class="question-item__stem">
{{ questionIndex }}{{ questionDetail.title }} <span v-if="props?.exam_status !== 1">{{ questionDetail.score }}分)</span>
{{ questionIndex }}{{ questionDetail.title }}
<span>{{ questionDetail.score }}分)</span>
</p>
<p class="question-item__content">{{ questionDetail.content }}</p>
<ul class="question-item__files">
<li class="question-item__files-item" v-for="(file, index) in questionDetail.files" :key="index">
<ul class="question-item__files" v-if="!!Object.keys(file).length">
<li class="question-item__files-item">
<el-icon><Document /></el-icon>
<div class="question-item__files-item__title">
<p>{{ file.name }}</p>
<p>{{ filesize(file.size) }}</p>
</div>
<a :href="file.url" target="_blank" download v-if="file.is_download">下载</a>
<a :href="file.url" target="_blank" download>下载</a>
<a :href="file.url" target="_blank">查看</a>
</li>
</ul>
......
<script setup lang="ts">
import { getExperimentScore } from '../api'
import { useAppConfig } from '@/composables/useAppConfig'
const appConfig = useAppConfig()
const ResultScoreViewAutoDialog = defineAsyncComponent(() => import('./ResultScoreViewAutoDialog.vue'))
interface Props {
experiment_id: string
}
import { useAppConfig } from '@/composables/useAppConfig'
const appConfig = useAppConfig()
const props = defineProps<Props>()
let experiment = $ref<any>()
......@@ -16,7 +19,7 @@ const classText = $computed(() => {
})
function fetchInfo() {
getExperimentScore({ experiment_id: props.experiment_id }).then(res => {
getExperimentScore({ experiment_id: props.experiment_id }).then((res) => {
experiment = res.data.experiment
let scoreDetails = []
try {
......@@ -28,7 +31,7 @@ function fetchInfo() {
}
detail = Object.assign(res.data.achievement, {
score: parseFloat(res.data.achievement.score),
score_details: scoreDetails
score_details: scoreDetails,
})
})
}
......@@ -42,13 +45,22 @@ function getOperationUrl(type: number) {
return `/student/lab/report/view/${experiment.id}`
} else if (type === 8) {
// 用户旅程
return `${appConfig.dmlURL || import.meta.env.VITE_DML_URL}/trip/my/score?experiment_id=${experiment.id}&student_id=${experiment.student.id}`
return `${appConfig.dmlURL || import.meta.env.VITE_DML_URL}/trip/my/score?experiment_id=${
experiment.id
}&student_id=${experiment.student.id}`
}
}
const autoVisible = ref(false)
const currentRow = ref(null)
function handleViewAuto(row: any) {
autoVisible.value = true
currentRow.value = row
}
</script>
<template>
<el-dialog title="实验成绩详情" width="600px">
<el-dialog title="实验成绩详情" width="800px">
<el-form label-width="120px" label-suffix=":" v-if="detail">
<el-form-item label="实验名称">{{ experiment.name }}</el-form-item>
<el-form-item label="实验课程名称">{{ experiment.course.name }}</el-form-item>
......@@ -71,7 +83,9 @@ function getOperationUrl(type: number) {
<el-row>
<el-col :span="12">
<el-form-item label="评分教师">
{{ detail.checker_sso_user.real_name || detail.checker_sso_user.nickname || detail.checker_sso_user.username }}
{{
detail.checker_sso_user.real_name || detail.checker_sso_user.nickname || detail.checker_sso_user.username
}}
</el-form-item>
</el-col>
<el-col :span="12">
......@@ -83,7 +97,11 @@ function getOperationUrl(type: number) {
<p>实验得分</p>
<p class="t1">{{ detail.score }}</p>
</div>
<el-table :data="detail.score_details" stripe :header-cell-style="{ background: '#ededed' }" v-if="detail.is_show === '1'">
<el-table
:data="detail.score_details"
stripe
:header-cell-style="{ background: '#ededed' }"
v-if="detail.is_show === '1'">
<el-table-column label="实验成绩组成项" prop="name" align="center"></el-table-column>
<el-table-column label="权重" prop="percent" align="center">
<template #default="{ row }">{{ row.percent }}%</template>
......@@ -99,6 +117,23 @@ function getOperationUrl(type: number) {
</template>
</template>
</el-table-column>
<el-table-column label="标准答案" align="center" width="80">
<template #default="{ row }">
<el-button type="primary" link @click="handleViewAuto(row)" v-if="[6, 7, 9, 11, 12].includes(row.type)"
>查看</el-button
>
</template>
</el-table-column>
<el-table-column label="我的答案" align="center" width="80">
<template #default="{ row }">
<el-button type="primary" @click="handleViewAuto(row)" link>查看</el-button>
</template>
</el-table-column>
<el-table-column label="评语" align="center" width="80" v-if="false">
<template #default="{ row }">
<el-button type="primary" link v-if="row.type === 9">查看</el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-form>
......@@ -107,6 +142,12 @@ function getOperationUrl(type: number) {
<el-button round auto-insert-space @click="$emit('update:modelValue', false)">关闭</el-button>
</el-row>
</template>
<ResultScoreViewAutoDialog
v-model="autoVisible"
:data="experiment"
:row="currentRow"
v-if="currentRow"></ResultScoreViewAutoDialog>
</el-dialog>
</template>
......
<script setup>
import AppList from '@/components/base/AppList.vue'
import { getExperimentScoreDetail } from '../api'
import { gradeRule } from '@/utils/dictionary'
import Preview from '@/components/Preview.vue'
import { useAppConfig } from '@/composables/useAppConfig'
const appConfig = useAppConfig()
const props = defineProps({
data: {
type: Object,
default: () => ({}),
},
row: {
type: Object,
default: () => ({}),
},
})
let datalist = $ref([])
function fetchInfo() {
getExperimentScoreDetail({
experiment_id: props.data.id,
type: props.row.type,
}).then((res) => {
datalist = res.data
})
}
watchEffect(() => {
fetchInfo()
})
const title = computed(() => {
return '查看' + gradeRule[props.row.type]
})
// 列表配置
const listOptions = computed(() => {
let columns = []
switch (props.row.type) {
case 6:
// 用户标签
columns = [
{ label: '序号', type: 'index', width: 60 },
{ label: '标签名称', prop: 'tag_name' },
{ label: '操作', prop: 'status', slots: 'table-x' },
]
break
case 7:
// 用户群组
columns = [
{ label: '序号', type: 'index', width: 60 },
{ label: '群组名称', prop: 'group_name' },
{ label: '操作', prop: 'status', slots: 'table-x' },
]
break
case 9:
// 营销资料
columns = [
{ label: '序号', type: 'index', width: 60 },
{ label: '资料名称', prop: 'material_name' },
{
label: '资料类型',
prop: 'type_name',
computed() {
return '文本'
},
},
{ label: '评语', prop: 'comment' },
{ label: '操作', prop: 'status', slots: 'table-x' },
]
break
case 12:
// 事件数据
columns = [
{ label: '序号', type: 'index', width: 60 },
{ label: '事件名称', prop: 'event_name' },
{ label: '操作', prop: 'status', slots: 'table-x' },
]
break
default:
break
}
return {
columns,
data: datalist,
}
})
function getOperationUrl(row) {
const type = props.row.type
const dmlURL = appConfig.dmlURL || import.meta.env.VITE_DML_URL
if (type === 6) {
// 用户标签
return `${dmlURL}/label?experiment_id=${props.data.id}&student_id=${props.data.student.id}&id=${row.tag_id}&name=${row.tag_name}`
} else if (type === 7) {
// 用户群组
return `${dmlURL}/group?experiment_id=${props.data.id}&student_id=${props.data.student.id}&id=${row.group_id}&name=${row.group_name}`
} else if (type === 9) {
// 营销资料
return `${dmlURL}/material?experiment_id=${props.data.id}&student_id=${props.data.student.id}&id=${row.material_id}&name=${row.material_name}`
} else if (type === 12) {
const url = row.file.url
// 事件数据
return ['pptx', 'doc', 'docx', 'xls', 'xlsx'].includes(url)
? `https://view.officeapps.live.com/op/view.aspx?src=${url}`
: url
}
}
</script>
<template>
<el-dialog :title="title" width="800px">
<template v-if="row.type === 11">
<Preview v-for="(item, index) in datalist" :key="index" :url="item.file.url"></Preview>
</template>
<AppList v-bind="listOptions" ref="appList" v-else>
<template #table-x="{ row }">
<el-button type="primary" link>
<a :href="getOperationUrl(row)" target="_blank">查看</a>
</el-button>
</template>
</AppList>
<template #footer>
<el-row justify="center">
<el-button round auto-insert-space @click="$emit('update:modelValue', false)">关闭</el-button>
</el-row>
</template>
</el-dialog>
</template>
......@@ -8,12 +8,16 @@ interface Props {
course_id?: string
}
const props = defineProps<Props>()
const emits = defineEmits(['empty'])
let list = $ref<ExperimentVideoType[]>([])
function fetchInfo() {
if (!props.experiment_id) return
getExperimentVideoList({ experiment_id: props.experiment_id }).then(res => {
getExperimentVideoList({ experiment_id: props.experiment_id }).then((res) => {
list = res.data.list
if (list.length === 0) {
emits('empty')
}
})
}
watchEffect(() => {
......@@ -33,8 +37,7 @@ const isEmpty = $computed(() => {
:key="item.id"
:data="item"
:course_id="course_id"
:experiment_id="experiment_id"
></VideoItem>
:experiment_id="experiment_id"></VideoItem>
</template>
</template>
......
......@@ -57,12 +57,16 @@ function handleCourseChange(value: string) {
ElMessageBox.confirm('切换实验,将会导致当前操作内容变化,请确认当前操作无误并确认切换实验。', '提示').then(() => {
form.course_id = value
form.experiment_id = ''
tabActive.value = 'info'
empty.value = []
})
}
// 实验改变
function handleExperimentChange(value: string) {
ElMessageBox.confirm('切换实验,将会导致当前操作内容变化,请确认当前操作无误并确认切换实验。', '提示').then(() => {
form.experiment_id = value
tabActive.value = 'info'
empty.value = []
})
}
......@@ -100,9 +104,9 @@ const examURL = ref('')
// 右侧
const cookies = useCookies(['TGC'])
const LAB_URL: any = computed(() => {
if (tabActive.value === 'exam' && examURL.value) return examURL.value
if (tabActive.value === 'exam' && examURL.value && experimentInfo?.exam_status === 1) return examURL.value
return experimentInfo?.type === 4
? `${appConfig.dmlURL || import.meta.env.VITE_DML_URL}/trip/my?experiment_id=${form.experiment_id}`
? `${appConfig.dmlURL || import.meta.env.VITE_DML_URL}?experiment_id=${form.experiment_id}`
: `${appConfig.dmlURL || import.meta.env.VITE_LAB_URL}&token=${cookies.get('TGC')}`
})
......@@ -225,10 +229,16 @@ function handleReportPreviewReady() {
isExport = false
}, 100)
}
const empty = ref<string[]>([])
function handleEmpty(name: string) {
empty.value.push(name)
}
</script>
<template>
<DragPanel @resize="handleResize" v-if="appConfig.system !== 'x'">
<DragPanel @resize="handleResize" :isLeftShow="appConfig.system === 'x' && experimentInfo?.exam_status === 1">
<template #left>
<div class="lab-left">
<el-form :model="form" label-suffix=":" hide-required-asterisk>
......@@ -243,29 +253,44 @@ function handleReportPreviewReady() {
</el-select>
</el-form-item>
</el-form>
<el-tabs type="border-card" v-model="tabActive">
<el-tab-pane label="实验信息" name="info" lazy>
<el-tabs type="border-card" v-model="tabActive" v-if="experimentInfo">
<el-tab-pane label="实验信息" name="info">
<Info :data="experimentInfo"></Info>
</el-tab-pane>
<el-tab-pane label="案例原文" lazy>
<Case :course_id="form.course_id" :experiment_id="form.experiment_id" :key="resizeKey"></Case>
<el-tab-pane label="案例原文" name="case" v-if="!empty.includes('case')">
<Case
:course_id="form.course_id"
:experiment_id="form.experiment_id"
:key="resizeKey"
@empty="handleEmpty('case')"></Case>
</el-tab-pane>
<el-tab-pane label="实训指导" lazy>
<Book :course_id="form.course_id" :experiment_id="form.experiment_id" :key="resizeKey"></Book>
<el-tab-pane label="实训指导" name="book" v-if="!empty.includes('book')">
<Book
:course_id="form.course_id"
:experiment_id="form.experiment_id"
:key="resizeKey"
@empty="handleEmpty('book')"></Book>
</el-tab-pane>
<el-tab-pane label="操作视频" lazy>
<Video :course_id="form.course_id" :experiment_id="form.experiment_id"></Video>
<el-tab-pane label="操作视频" name="video" v-if="!empty.includes('video')">
<Video
:course_id="form.course_id"
:experiment_id="form.experiment_id"
@empty="handleEmpty('video')"></Video>
</el-tab-pane>
<el-tab-pane label="理论考试" name="exam" lazy>
<Exam :experiment_id="form.experiment_id" v-model="examURL"></Exam>
<el-tab-pane label="理论试题" name="exam" v-if="!empty.includes('exam')">
<Exam
:experiment_id="form.experiment_id"
v-model="examURL"
:examStatus="experimentInfo?.exam_status"
@empty="handleEmpty('exam')"></Exam>
</el-tab-pane>
<el-tab-pane label="实验试题" name="qa" lazy>
<Question :experiment_id="form.experiment_id"></Question>
<el-tab-pane label="实操试题" name="qa" v-if="!empty.includes('qa')">
<Question :experiment_id="form.experiment_id" @empty="handleEmpty('qa')"></Question>
</el-tab-pane>
<el-tab-pane label="过程与结果" lazy>
<el-tab-pane label="过程与结果" name="result" lazy>
<Result :data="experimentInfo" @update="fetchExperimentRecord"></Result>
</el-tab-pane>
<el-tab-pane label="讨论交流" lazy>
<el-tab-pane label="讨论交流" name="discuss" lazy>
<Discuss :experiment_id="form.experiment_id"></Discuss>
</el-tab-pane>
</el-tabs>
......@@ -273,7 +298,11 @@ function handleReportPreviewReady() {
</template>
<template #right>
<AppCard>
<el-row justify="space-between">
<div class="exam-status" v-if="appConfig.system === 'x' && experimentInfo?.exam_status === 1">
<el-button type="primary" @click="tabActive = 'qa'">实操系统</el-button>
<el-button type="primary" @click="tabActive = 'exam'">理论试题</el-button>
</div>
<el-row justify="space-between" v-else>
<div>
<el-button type="primary" :icon="HomeFilled" :disabled="submitted" @click="handleBackHome"
>返回首页</el-button
......@@ -315,130 +344,25 @@ function handleReportPreviewReady() {
</el-row>
</AppCard>
<div class="lab-box">
<el-empty description="您已经提交该实验,不能再进行操作,切换其他实验再做操作吧。" v-if="submitted" />
<iframe
allow="camera; microphone"
allowfullscreen
:src="LAB_URL"
:key="iframeKey"
frameborder="0"
class="iframe"
ref="iframeRef"
v-else></iframe>
</div>
</template>
</DragPanel>
<DragPanel v-else @resize="handleResize" :isLeftShow="experimentInfo?.exam_status">
<template #left>
<div class="lab-left">
<el-form :model="form" label-suffix=":" hide-required-asterisk>
<el-form-item label="请选择课程">
<el-select :model-value="form.course_id" @change="handleCourseChange" style="width: 100%">
<el-option v-for="item in courses" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="请选择实验" prop="experiment_id">
<el-select :model-value="form.experiment_id" @change="handleExperimentChange" style="width: 100%">
<el-option v-for="item in experimentList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
</el-form>
<el-tabs type="border-card" v-model="tabActive">
<el-tab-pane :label="experimentInfo?.exam_status === 0 ? '实验训练' : '实验试题'" name="qa" lazy>
<Exam
:experiment_id="form.experiment_id"
v-model="examURL"
:examStatus="experimentInfo?.exam_status"
v-if="experimentInfo?.exam_status === 0"></Exam>
<Question :experiment_id="form.experiment_id" v-else></Question>
</el-tab-pane>
<el-tab-pane
label="理论考试"
name="exam"
lazy
v-show="experimentInfo?.exam_status === 1 && tabActive === 'exam'">
<Exam :experiment_id="form.experiment_id" v-model="examURL"></Exam>
</el-tab-pane>
<el-tab-pane label="实验信息" lazy>
<Info :data="experimentInfo"></Info>
</el-tab-pane>
<el-tab-pane label="案例原文" lazy>
<Case :course_id="form.course_id" :experiment_id="form.experiment_id" :key="resizeKey"></Case>
</el-tab-pane>
<el-tab-pane label="实训指导" lazy>
<Book :course_id="form.course_id" :experiment_id="form.experiment_id" :key="resizeKey"></Book>
</el-tab-pane>
<el-tab-pane label="操作视频" lazy>
<Video :course_id="form.course_id" :experiment_id="form.experiment_id"></Video>
</el-tab-pane>
<el-tab-pane label="讨论交流" lazy>
<Discuss :experiment_id="form.experiment_id"></Discuss>
</el-tab-pane>
<el-tab-pane label="过程与结果" lazy>
<Result :data="experimentInfo" @update="fetchExperimentRecord"></Result>
</el-tab-pane>
</el-tabs>
</div>
</template>
<template #right>
<div class="exam-status" v-if="appConfig.system === 'x' && experimentInfo?.exam_status === 1">
<el-button type="primary" @click="tabActive = 'qa'">实操系统</el-button>
<el-button type="primary" @click="tabActive = 'exam'">理论试题</el-button>
</div>
<AppCard v-else>
<el-row justify="space-between">
<div>
<el-button type="primary" :icon="HomeFilled" :disabled="submitted" @click="handleBackHome"
>返回首页</el-button
>
<el-button type="primary" :disabled="disabled" @click="handleSubmit">提交实验</el-button>
<el-empty
description="您已经提交该实验,不能再进行操作,切换其他实验再做操作吧。"
style="flex: 1"
v-if="submitted" />
<template v-else>
<iframe
allow="camera; microphone"
allowfullscreen
:src="LAB_URL"
:key="iframeKey"
frameborder="0"
class="iframe"
ref="iframeRef"></iframe>
<div
style="padding: 10px; background-color: #fff; max-width: 300px; min-width: 300px"
v-if="experimentInfo?.exam_status === 1 && tabActive === 'qa'">
<Question :experiment_id="form.experiment_id" :exam_status="experimentInfo?.exam_status"></Question>
</div>
<div>
<el-button type="primary" :disabled="disabled" :loading="screenshotLoading" @click="handleCapture"
>截图</el-button
>
<el-button type="primary" :disabled="disabled" @click="prepareDialogVisible = true">实验准备</el-button>
<el-button type="primary" :disabled="disabled" @click="resultDialogVisible = true">实验结果</el-button>
<el-button
type="primary"
:disabled="disabled"
v-if="experimentInfo?.report_upload_way === 2 && !experimentInfo?.is_commit_report">
<router-link :to="`/student/lab/report/${form.experiment_id}`" target="_blank">在线实验报告</router-link>
</el-button>
<el-button
type="primary"
:disabled="disabled"
@click="reportDialogVisible = true"
v-if="experimentInfo?.report_upload_way === 1 && !submitted"
>上传实验报告</el-button
>
<el-button type="primary" @click="handleReportView" v-if="experimentInfo?.is_commit_report"
>查看实验报告</el-button
>
<el-button
type="primary"
@click="handleReportExport"
v-if="detail?.status === 2 && experimentInfo?.is_commit_report"
>导出实验报告</el-button
>
</div>
</el-row>
</AppCard>
<div class="lab-box">
<el-empty description="您已经提交该实验,不能再进行操作,切换其他实验再做操作吧。" v-if="submitted" />
<iframe
allowfullscreen
:src="LAB_URL"
:key="iframeKey"
frameborder="0"
class="iframe"
ref="iframeRef"
v-else></iframe>
<div
style="padding: 10px; background-color: #fff; max-width: 300px; min-width: 300px"
v-if="experimentInfo?.exam_status === 1 && tabActive === 'qa'">
<Question :experiment_id="form.experiment_id" :exam_status="experimentInfo?.exam_status"></Question>
</div>
</template>
</div>
</template>
</DragPanel>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论