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

chore: 新增数字教材

上级 0c77c29c
差异被折叠。
......@@ -50,6 +50,7 @@
"typescript": "~4.7.4",
"unplugin-auto-import": "^0.11.3",
"vite": "^3.1.8",
"vite-plugin-mkcert": "^1.17.6",
"vue-tsc": "^1.0.9"
}
}
......@@ -145,3 +145,9 @@ export function submitPaper(data: {
*
* 考试、测验end
*/
export function getCourseBook(data: { id: string }) {
return httpRequest.post('/api/ebook/open/teacher/book/getInfoById', data, {
headers: { 'Content-Type': 'application/json' }
})
}
......@@ -28,6 +28,8 @@ const targetUrl = computed(() => {
return `/course/exam?course_id=${courseId}&semester_id=${semesterId}&paper_id=${props.data.resource_id}&type=2&paper_title=${props.data.name}`
} else if (props.data.resource_type === 6) {
return info.join_url
} else if (props.data.resource_type === 13) {
return `https://zijingebook.ezijing.com/student/book?book_id=${info.book_id}`
} else {
return `/preview?course_id=${courseId}&semester_id=${semesterId}&resource_id=${props.data.resource_id}&resource_type=${props.data.resource_type}&url=${info.url}`
}
......@@ -95,8 +97,7 @@ function downloadFile(data: CourseResourceType) {
: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"
>
v-if="data.paper_status === 2 || data.paper_status === 3">
<el-button round size="small">查看报告</el-button>
</router-link>
<template v-if="data.resource_type === 6 && data.info">
......@@ -108,8 +109,7 @@ function downloadFile(data: CourseResourceType) {
class="icon-star"
:class="!!data.collection_count ? 'is-active' : ''"
@click="toggleCollection(data)"
v-if="canCollection(data.resource_type)"
></i>
v-if="canCollection(data.resource_type)"></i>
<i class="icon-download" @click="downloadFile(data)" v-if="!!data.can_download"><Download /></i>
</div>
</div>
......
<!-- 直播 -->
<script setup lang="ts">
import CoursePlayerResourceListItem from './CoursePlayerResourceListItem.vue'
import { getCourseBook } from '../api'
const props = defineProps<{ bookId: string }>()
const list = ref([])
function fetchInfo() {
if (!props.bookId) return
getCourseBook({ id: props.bookId }).then(res => {
const book = res.data
const resource = {
id: book.id,
name: book.name,
resource_id: book.id,
resource_type: 13,
info: { book_id: book.id, name: book.name }
}
list.value = [resource]
})
}
onMounted(() => {
fetchInfo()
})
</script>
<template>
<div class="list">
<template v-if="list.length">
<CoursePlayerResourceListItem v-for="item in list" :data="item" :key="item.id" />
</template>
<el-empty description="暂无数据" v-else />
</div>
</template>
......@@ -111,6 +111,8 @@ function targetUrl(resource: CourseResourceType, section: CourseSectionType, cha
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}`
} else if (resource.resource_type === 6) {
return resource.info.join_url
} else if (resource.resource_type === 13) {
return `https://zijingebook.ezijing.com/student/book?book_id=${resource.info.book_id}&chapter_id=${resource.info.chapter_id}`
} else {
return `/preview?course_id=${courseId}&semester_id=${semesterId}&resource_id=${resource.resource_id}&resource_type=${resource.resource_type}&url=${resource.info?.url}`
}
......
<script setup lang="ts">
import type { CourseResourceType, CourseChapterType } from '../types'
import { getCourseSection, getChapterTreeList } from '../api'
import { getCourse, getCourseSection, getChapterTreeList } from '../api'
import CoursePlayerResourceList from '../components/CoursePlayerResourceList.vue'
import { ArrowLeftBold, ArrowRightBold } from '@element-plus/icons-vue'
import type { VideoJsPlayer } from 'video.js'
......@@ -10,6 +10,7 @@ const { mobile } = useDevice()
const CoursePlayerVideo = defineAsyncComponent(() => import('../components/CoursePlayerVideo.vue'))
const CoursePlayerChapter = defineAsyncComponent(() => import('../components/CoursePlayerChapter.vue'))
const CourseViewBook = defineAsyncComponent(() => import('../components/CourseViewBook.vue'))
const route = useRoute()
let courseId = $ref<string>('')
......@@ -53,6 +54,19 @@ function fetchInfo() {
watchEffect(() => {
fetchInfo()
})
// 获取课程详情信息
const course = ref({ name: '', ebook_id: '' })
function fetchCourseInfo() {
if (!courseId || !semesterId) return
getCourse({ course_id: courseId, semester_id: semesterId }).then(res => {
course.value = res.data.detail
})
}
watchEffect(() => {
fetchCourseInfo()
})
let chapterList = $ref<CourseChapterType[]>([])
// 获取章节列表
function fetchList() {
......@@ -97,7 +111,11 @@ function toggleSidebar() {
</div>
<div class="course-player-bd">
<div class="course-player-main" v-loading="loading">
<CoursePlayerVideo :chapterList="chapterList" :key="sectionId" @updateResource="onUpdateResource" @timeupdate="onTimeUpdate" />
<CoursePlayerVideo
:chapterList="chapterList"
:key="sectionId"
@updateResource="onUpdateResource"
@timeupdate="onTimeUpdate" />
<el-tabs :stretch="mobile">
<el-tab-pane label="课件">
<CoursePlayerResourceList :list="detail.coursewares" />
......@@ -117,11 +135,18 @@ function toggleSidebar() {
<el-tab-pane label="直播" lazy>
<CoursePlayerResourceList :list="detail.meetings" />
</el-tab-pane>
<el-tab-pane label="数字教材" lazy>
<CourseViewBook :bookId="course.ebook_id"></CourseViewBook>
</el-tab-pane>
</el-tabs>
</div>
<div class="course-player-aside" :class="{ 'is-hidden': !sidebarVisible }">
<div class="course-player-aside__inner">
<CoursePlayerChapter :chapterList="chapterList" :pptList="pptList" :pptIndex="pptIndex" @clickPPT="onClickPPT" />
<CoursePlayerChapter
:chapterList="chapterList"
:pptList="pptList"
:pptIndex="pptIndex"
@clickPPT="onClickPPT" />
</div>
<div class="toggle-button" :class="{ 'is-hidden': !sidebarVisible }" @click="toggleSidebar">
<el-icon>
......
......@@ -14,6 +14,7 @@ const CourseViewExam = defineAsyncComponent(() => import('../components/CourseVi
const CourseViewAssess = defineAsyncComponent(() => import('../components/CourseViewAssess.vue'))
const CourseViewLive = defineAsyncComponent(() => import('../components/CourseViewLive.vue'))
const CourseViewMaterial = defineAsyncComponent(() => import('../components/CourseViewMaterial.vue'))
const CourseViewBook = defineAsyncComponent(() => import('../components/CourseViewBook.vue'))
const { query } = useRoute()
const courseId = $ref<string | null>(query.course_id as string)
......@@ -117,8 +118,7 @@ const handleDetail = function () {
<div
:class="infoIndex === 1 ? 'btn active' : 'btn'"
@click="showInfo(props.data?.previous_preparation, 1)"
v-if="false"
>
v-if="false">
预备知识
</div>
<div :class="infoIndex === 2 ? 'btn active' : 'btn'" @click="showInfo(props.data?.target, 2)">
......@@ -177,6 +177,9 @@ const handleDetail = function () {
<el-tab-pane label="资料" lazy>
<CourseViewMaterial />
</el-tab-pane>
<el-tab-pane label="数字教材" lazy>
<CourseViewBook :bookId="detail.ebook_id"></CourseViewBook>
</el-tab-pane>
</el-tabs>
</div>
<template v-if="props.data?.length !== 1">
......
......@@ -58,7 +58,7 @@ httpRequest.interceptors.response.use(
return Promise.reject(data)
}
if (Object.hasOwnProperty.call(data, 'code') && data.code !== 0) {
if (Object.hasOwnProperty.call(data, 'code') && data.code !== 0 && data.code !== 200) {
ElMessage.error(data.message || data.msg)
return Promise.reject(data)
}
......
import fs from 'fs'
import path from 'path'
// import fs from 'fs'
// import path from 'path'
import { fileURLToPath, URL } from 'url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import mkcert from 'vite-plugin-mkcert'
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => ({
base: mode === 'prod' ? 'https://webapp-pub.ezijing.com/website/prod/saas-learn/' : '/',
plugins: [
mkcert(),
vue({ reactivityTransform: true }),
AutoImport({
imports: ['vue', 'vue/macros', 'vue-router'],
......@@ -25,10 +27,10 @@ export default defineConfig(({ mode }) => ({
server: {
open: true,
host: 'dev.ezijing.com',
https: {
key: fs.readFileSync(path.join(__dirname, './https/dev.ezijing.com.key')),
cert: fs.readFileSync(path.join(__dirname, './https/dev.ezijing.com.pem'))
},
// https: {
// key: fs.readFileSync(path.join(__dirname, './https/dev.ezijing.com.key')),
// cert: fs.readFileSync(path.join(__dirname, './https/dev.ezijing.com.pem'))
// },
proxy: {
'/api': 'https://saas-learn.ezijing.com'
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论