提交 93dc694f authored 作者: 王鹏飞's avatar 王鹏飞

chore: update

上级 f1424aff
......@@ -9,7 +9,7 @@ const userInfo = userStore.user
const logout = async () => {
await userStore.logout()
location.href = `${import.meta.env.VITE_LOGIN_URL}?rd=${encodeURIComponent(location.href)}`
location.href = `${import.meta.env.VITE_LOGIN_URL}?rd=${encodeURIComponent(location.origin)}`
}
</script>
......
<script setup lang="ts">
import type { PaperQuestionType } from '@/types'
import { ElMessage } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
import { ArrowLeftBold } from '@element-plus/icons-vue'
import { cachePaper, submitPaper } from '../api'
......@@ -64,6 +64,32 @@ function handleNext() {
}
// 提交
function handleSubmit() {
// 未作答的数量
const unansweredNum = questionList.reduce((result, item) => {
if (item.children && item.children.length) {
item.children.forEach(item => {
!item.user_answer && result++
})
} else {
!item.user_answer && result++
}
return result
}, 0)
if (unansweredNum) {
ElMessageBox.confirm(`您还有${unansweredNum}道题没有作答`, '请确认', {
confirmButtonText: '确认提交',
cancelButtonText: '继续作答',
type: 'warning'
}).then(() => {
handleSubmitPaper()
})
} else {
handleSubmitPaper()
}
}
// 提交试卷
function handleSubmitPaper() {
submitLoading = true
clearInterval(timer)
submitPaper({
......@@ -81,8 +107,8 @@ function handleSubmit() {
submitLoading = false
})
}
// 自动提交
function handleAutoSubmit() {
// 提交缓存试卷
function handleSubmitCachePaper() {
if (disabled) return
cachePaper({
course_id: courseId,
......@@ -92,7 +118,7 @@ function handleAutoSubmit() {
question: JSON.stringify(genSubmitQuestion(questionList))
})
}
const timer = setInterval(handleAutoSubmit, 5000)
const timer = setInterval(handleSubmitCachePaper, 5000)
onUnmounted(() => {
clearInterval(timer)
})
......@@ -122,13 +148,18 @@ function genSubmitQuestion(questionList: PaperQuestionType[]) {
<div class="course-exam-card-bd">
<div class="course-exam-left">
<div class="course-exam-scroll">
<CourseExamQuestion :question="currentQuestion" :status="status" :index="questionIndex + 1">
<CourseExamQuestion
:question="currentQuestion"
:status="status"
:index="questionIndex + 1"
v-if="questionLength"
>
<template #index>{{ questionIndex + 1 }}/{{ questionLength }}</template>
</CourseExamQuestion>
</div>
<div class="course-exam-buttons">
<el-button size="large" :disabled="questionIndex === 0" @click="handlePrev">上一题</el-button>
<el-button size="large" :disabled="questionIndex === questionLength - 1" @click="handleNext">
<el-button size="large" :disabled="questionIndex >= questionLength - 1" @click="handleNext">
下一题
</el-button>
</div>
......
......@@ -5,6 +5,7 @@ const router = useRouter()
const courseId = $ref<string>(inject('courseId'))
const semesterId = $ref<string>(inject('semesterId'))
const paperId = $ref<string>(inject('paperId'))
const paperTitle = $ref<string>(inject('paperTitle'))
const type = $ref<string>(inject('type'))
// 所有试题
const questionList = $ref<PaperQuestionType[]>(inject('questionList'))
......@@ -34,7 +35,7 @@ function genClass(data: PaperQuestionType) {
function handleClick(index: number) {
router.push({
path: '/course/exam',
query: { course_id: courseId, semester_id: semesterId, paper_id: paperId, type, index }
query: { course_id: courseId, semester_id: semesterId, paper_id: paperId, type, index, paper_title: paperTitle }
})
}
</script>
......@@ -106,7 +107,7 @@ function handleClick(index: number) {
border: 2px solid #ccc;
color: #666;
&:nth-child(5n) {
&:nth-child(10n) {
margin-right: 0;
}
}
......@@ -140,6 +141,11 @@ function handleClick(index: number) {
color: #666;
border: 2px solid #ccc;
}
.is-error {
color: #666;
border: 2px solid #c01540;
}
.is-review {
color: #fff;
background-color: blue;
......@@ -160,8 +166,4 @@ function handleClick(index: number) {
.is-info.is-success {
color: #fff;
}
.is-error {
color: #666;
border: 2px solid #c01540;
}
</style>
......@@ -21,7 +21,7 @@ const props = defineProps<Props>()
const targetUrl = computed(() => {
const info = props.data.info
if (props.data.resource_type === 3 || props.data.resource_type === 9) {
return `/course/exam?course_id=${courseId}&semester_id=${semesterId}&paper_id=${props.data.resource_id}&type=2`
return `/course/exam?course_id=${courseId}&semester_id=${semesterId}&paper_id=${props.data.resource_id}&type=2&paper_title=${props.data.name}`
} else if (['pptx', 'doc', 'docx', 'xls', 'xlsx'].includes(info.type)) {
return `https://view.officeapps.live.com/op/view.aspx?src=${info.url}`
} else {
......@@ -70,7 +70,7 @@ function downloadFile(data: CourseResourceType) {
</a>
</p>
<router-link
:to="`/course/exam/result?course_id=${courseId}&semester_id=${semesterId}&paper_id=${data.resource_id}&type=2`"
:to="`/course/exam/result?course_id=${courseId}&semester_id=${semesterId}&paper_id=${data.resource_id}&type=2&paper_title=${data.name}`"
target="_blank"
style="margin: 0 20px"
v-if="data.paper_status === 2 || data.paper_status === 3"
......
......@@ -41,7 +41,7 @@ const section = $computed(() => {
// 当前节
const resource = $computed(() => {
return section?.resources.find(item => item.resource_id === resourceId)
return section?.resources.find(item => item.resource_id === resourceId && item.resource_type === 2)
})
// 资源视频列表
const videoList = $computed<CourseResourceType[]>(() => {
......@@ -70,40 +70,41 @@ const currentPlayList = $computed<PlayItemType[]>(() => {
})
// 获取视频信息
function fetchInfo() {
if (!resource?.info.source_id) return
return getCoursePlayInfo({ source_id: resource.info.source_id }).then(res => {
playList = res.data.playing_list
changeSrc(currentPlayList[0])
})
async function fetchInfo() {
if (!resource?.info.source_id) throw '资源不存在'
const res = await getCoursePlayInfo({ source_id: resource.info.source_id })
playList = res.data.playing_list
}
// 获取视频记录
function fetchVideoRecords() {
if (!resource) return
getVideoRecords({
async function fetchVideoRecords() {
if (!resource) throw '资源不存在'
const res = await getVideoRecords({
chapter_id: chapterId,
course_id: courseId,
section_id: sectionId,
semester_id: semesterId,
video_id: resourceId
}).then(res => {
const { detail = {} } = res.data
progress.current_playing_time = detail.current_playing_time ? parseFloat(detail.current_playing_time) : 0
progress.max_playing_time = detail.max_playing_time ? parseFloat(detail.max_playing_time) : 0
progress.valid_playing_time = detail.valid_playing_time ? parseFloat(detail.valid_playing_time) : 0
progress.watchedTimePoint = []
if (videoJsPlayer && progress.current_playing_time) {
videoJsPlayer.currentTime(progress.current_playing_time)
}
})
const { detail = {} } = res.data
progress.current_playing_time = detail.current_playing_time ? parseFloat(detail.current_playing_time) : 0
progress.max_playing_time = detail.max_playing_time ? parseFloat(detail.max_playing_time) : 0
progress.valid_playing_time = detail.valid_playing_time ? parseFloat(detail.valid_playing_time) : 0
progress.watchedTimePoint = []
}
watchEffect(async () => {
if (!resource) return
await fetchVideoRecords()
await fetchInfo()
fetchVideoRecords()
changeSrc(currentPlayList[0])
nextTick(() => {
if (videoJsPlayer && progress.current_playing_time) {
videoJsPlayer.currentTime(progress.current_playing_time)
console.log('seek', progress.current_playing_time)
}
})
})
const throttledFn = throttle(
() => {
if (progress.watchedTimePoint.length < 5) return
uploadVideoRecords({
chapter_id: chapterId,
course_id: courseId,
......@@ -118,27 +119,17 @@ const throttledFn = throttle(
// 清空已经上传过的观看时间点
progress.watchedTimePoint = []
},
5000,
{ leading: false }
5000
// { leading: false }
)
let watchedTime = 0
function onTimeUpdate() {
console.log('onTimeUpdate')
if (!videoJsPlayer) return
const time = Math.floor(videoJsPlayer.currentTime() ?? 0)
// 更新当前播放时间
progress.current_playing_time = time
// 观看的最大点
progress.max_playing_time = Math.max(time, progress.max_playing_time)
// 观看时间点
const hasTimePoint = progress.watchedTimePoint.includes(time)
if (!hasTimePoint) {
progress.watchedTimePoint.push(time)
}
if (!time) return
console.log('onTimeUpdate', time)
// 更新观看累计时长
if (time !== watchedTime) {
watchedTime = time
if (time !== progress.current_playing_time) {
// // 增加跳过片头时间
// if (this.isSkip && !this.progress.pt) {
// this.progress.pt = this.skipTime + 20
......@@ -147,6 +138,14 @@ function onTimeUpdate() {
progress.valid_playing_time = progress.valid_playing_time || 20
progress.valid_playing_time++
}
// 更新当前播放时间
progress.current_playing_time = time
// 观看的最大点
progress.max_playing_time = Math.max(time, progress.max_playing_time)
// 观看时间点
const hasTimePoint = progress.watchedTimePoint.includes(time)
!hasTimePoint && progress.watchedTimePoint.push(time)
throttledFn()
}
......@@ -162,15 +161,17 @@ const isAutoPlayNext = useStorage('isAutoPlayNext', false)
let isReady = $ref<boolean>(false)
let videoJsPlayer = $ref<VideoJsPlayer | null>()
const onReady = (player: VideoJsPlayer) => {
videoJsPlayer = player
isReady = true
videoJsPlayer = player
videoJsPlayer.currentTime(progress.current_playing_time)
console.log('seek', progress.current_playing_time)
}
function changeSrc(data: PlayItemType) {
// src = { src: data.PlayURL, type: 'application/x-mpegURL' }
src = { src: data.PlayURL, type: 'video/mp4' }
}
function changeResource(data: CourseResourceType) {
throttledFn && throttledFn.cancel()
throttledFn && throttledFn.flush()
resourceId = data.resource_id
}
</script>
......
......@@ -81,9 +81,9 @@ function downloadFile(data: CourseResourceType) {
// 跳转链接
function targetUrl(resource: CourseResourceType, section: CourseSectionType, chapter: CourseChapterType) {
if (resource.resource_type === 3 || resource.resource_type === 9) {
return `/course/exam?course_id=${courseId}&semester_id=${semesterId}&paper_id=${resource.resource_id}&type=2`
return `/course/exam?course_id=${courseId}&semester_id=${semesterId}&paper_id=${resource.resource_id}&type=2&paper_title=${resource.name}`
}
return `/course/player?course_id=${courseId}&chapter_id=${chapter.id}&section_id=${section.id}&resource_id=${resource.resource_id}&semester_id=${semesterId}`
return `/course/player?course_id=${courseId}&chapter_id=${chapter.id}&section_id=${section.id}&resource_id=${resource.resource_id}&semester_id=${semesterId}&paper_title=${resource.name}`
}
</script>
<template>
......@@ -102,7 +102,7 @@ function targetUrl(resource: CourseResourceType, section: CourseSectionType, cha
</router-link>
</p>
<router-link
:to="`/course/exam/result?course_id=${courseId}&semester_id=${semesterId}&paper_id=${resource.resource_id}&type=2`"
:to="`/course/exam/result?course_id=${courseId}&semester_id=${semesterId}&paper_id=${resource.resource_id}&type=2&paper_title=${resource.name}`"
target="_blank"
style="margin: 0 20px"
v-if="resource.paper_status === 2 || resource.paper_status === 3"
......
......@@ -14,13 +14,13 @@ const semesterId = $ref(query.semester_id as string)
<div class="course-exam-item" :key="data.id">
<p>
<router-link
:to="`/course/exam?course_id=${courseId}&semester_id=${semesterId}&paper_id=${data.id}&type=1`"
:to="`/course/exam?course_id=${courseId}&semester_id=${semesterId}&paper_id=${data.id}&type=1&paper_title=${data.paper_title}`"
target="_blank"
>{{ data.paper_title }}</router-link
>
</p>
<router-link
:to="`/course/exam/result?course_id=${courseId}&semester_id=${semesterId}&paper_id=${data.id}&type=1`"
:to="`/course/exam/result?course_id=${courseId}&semester_id=${semesterId}&paper_id=${data.id}&type=1&paper_title=${data.paper_title}`"
target="_blank"
v-if="data.paper_status === 2 || data.paper_status === 3"
>
......
......@@ -7,6 +7,7 @@ const route = useRoute()
const courseId = $ref(route.query.course_id as string)
const semesterId = $ref(route.query.semester_id as string)
const paperId = $ref(route.query.paper_id as string)
const paperTitle = $ref(route.query.paper_title as string)
const type = $ref(parseInt(route.query.type as string))
const detail = reactive({ status: 1 })
let questionList = $ref<PaperQuestionType[]>([])
......@@ -26,8 +27,12 @@ function fetchInfo() {
onMounted(() => {
fetchInfo()
})
const title = computed(() => {
if (paperTitle) return paperTitle
return type === 1 ? '课程考试' : '课后作业'
})
</script>
<template>
<CourseExamCard :status="detail.status" @update="fetchInfo" v-loading="loading"></CourseExamCard>
<CourseExamCard :status="detail.status" :title="title" @update="fetchInfo" v-loading="loading"></CourseExamCard>
</template>
......@@ -10,6 +10,8 @@ const semesterId = $ref(route.query.semester_id as string)
provide('semesterId', semesterId)
const paperId = $ref(route.query.paper_id as string)
provide('paperId', paperId)
const paperTitle = $ref(route.query.paper_title as string)
provide('paperTitle', paperTitle)
const type = $ref(parseInt(route.query.type as string))
provide('type', type)
......
......@@ -85,7 +85,7 @@ function downloadFile(data: CollectionType) {
}
function targetUrl(item: CollectionType) {
if (item.type === 5) {
return `/course/exam?course_id=${item.course_id}&semester_id=${item.semester_id}&paper_id=${item.info.id}&type=2`
return `/course/exam?course_id=${item.course_id}&semester_id=${item.semester_id}&paper_id=${item.info.id}&type=2&paper_title=${item.info.paper_title}`
}
return `/course/player?course_id=${item.course_id}&chapter_id=${item.chapter_id}&section_id=${item.section_id}&resource_id=${item.source_id}&semester_id=${item.semester_id}`
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论