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

chore: update

上级 cc9a93d1
...@@ -60,7 +60,7 @@ export function submitCourseWork(data: { ...@@ -60,7 +60,7 @@ export function submitCourseWork(data: {
return httpRequest.post('/api/learn/api/v1/job/submit', data) return httpRequest.post('/api/learn/api/v1/job/submit', data)
} }
// 获取课程直播列表 // 获取课程考试列表
export function getCourseExamList(params: { course_id: string; semester_id: string }) { export function getCourseExamList(params: { course_id: string; semester_id: string }) {
return httpRequest.get('/api/learn/api/v1/question-bank/papers', { params }) return httpRequest.get('/api/learn/api/v1/question-bank/papers', { params })
} }
...@@ -70,6 +70,11 @@ export function getCourseLiveList(data: { course_id: string; semester_id: string ...@@ -70,6 +70,11 @@ export function getCourseLiveList(data: { course_id: string; semester_id: string
return httpRequest.post('/api/learn/api/v1/meeting/list', data) return httpRequest.post('/api/learn/api/v1/meeting/list', data)
} }
// 获取课程资料列表
export function getCourseMaterialList(params: { course_id: string; semester_id: string }) {
return httpRequest.get(`/api/learn/api/v1/course/${params.course_id}/${params.semester_id}/informations`, { params })
}
// 获取课程小节信息 // 获取课程小节信息
export function getCourseSection(data: { section_id: string; semester_id: string }) { export function getCourseSection(data: { section_id: string; semester_id: string }) {
return httpRequest.post('/api/learn/api/v1/chapter/section/detail', data) return httpRequest.post('/api/learn/api/v1/chapter/section/detail', data)
......
...@@ -55,10 +55,10 @@ function toggleCollection(data: CourseResourceType) { ...@@ -55,10 +55,10 @@ function toggleCollection(data: CourseResourceType) {
} }
// 是否可以下载 // 是否可以下载
function canDownload(type: number) { // function canDownload(type: number) {
// return [4, 10, 11].includes(type) // // return [4, 10, 11].includes(type)
return [4].includes(type) // return [4].includes(type)
} // }
// 下载资源 // 下载资源
function downloadFile(data: CourseResourceType) { function downloadFile(data: CourseResourceType) {
const { url, name } = data.info const { url, name } = data.info
...@@ -110,7 +110,7 @@ function downloadFile(data: CourseResourceType) { ...@@ -110,7 +110,7 @@ function downloadFile(data: CourseResourceType) {
@click="toggleCollection(data)" @click="toggleCollection(data)"
v-if="canCollection(data.resource_type)" v-if="canCollection(data.resource_type)"
></i> ></i>
<i class="icon-download" @click="downloadFile(data)" v-if="canDownload(data.resource_type)"><Download /></i> <i class="icon-download" @click="downloadFile(data)" v-if="!!data.can_download"><Download /></i>
</div> </div>
</div> </div>
</template> </template>
......
...@@ -77,10 +77,10 @@ function toggleCollection(resource: CourseResourceType, section: CourseSectionTy ...@@ -77,10 +77,10 @@ function toggleCollection(resource: CourseResourceType, section: CourseSectionTy
}) })
} }
// 是否可以下载 // 是否可以下载
function canDownload(type: number) { // function canDownload(type: number) {
// return [4, 10, 11].includes(type) // // return [4, 10, 11].includes(type)
return [4].includes(type) // return [4].includes(type)
} // }
// 下载资源 // 下载资源
function downloadFile(data: CourseResourceType) { function downloadFile(data: CourseResourceType) {
const { url, name } = data.info const { url, name } = data.info
...@@ -156,7 +156,7 @@ function targetUrl(resource: CourseResourceType, section: CourseSectionType, cha ...@@ -156,7 +156,7 @@ function targetUrl(resource: CourseResourceType, section: CourseSectionType, cha
@click="toggleCollection(resource, section, item)" @click="toggleCollection(resource, section, item)"
v-if="canCollection(resource)" v-if="canCollection(resource)"
></i> ></i>
<i class="icon-download" @click="downloadFile(resource)" v-if="canDownload(resource.resource_type)"> <i class="icon-download" @click="downloadFile(resource)" v-if="!!resource.can_download">
<Download /> <Download />
</i> </i>
</div> </div>
......
<!-- 直播 -->
<script setup lang="ts">
import type { LiveType } from '@/types'
import CourseViewMaterialListItem from './CourseViewMaterialListItem.vue'
import { getCourseMaterialList } from '../api'
const { query } = useRoute()
const courseId = $ref(query.course_id as string)
const semesterId = $ref(query.semester_id as string)
let list = $ref<LiveType[]>([])
function fetchList() {
getCourseMaterialList({ course_id: courseId, semester_id: semesterId }).then(res => {
list = res.data.items
})
}
onMounted(() => {
fetchList()
})
</script>
<template>
<div class="course-live">
<template v-if="list.length">
<CourseViewMaterialListItem v-for="item in list" :data="item" :key="item.id"></CourseViewMaterialListItem>
</template>
<el-empty description="暂无数据" v-else />
</div>
</template>
<script setup lang="ts">
import type { CourseResourceType } from '../types'
import ResourceIcon from '@/components/ResourceIcon.vue'
import { Download } from '@element-plus/icons-vue'
import { saveAs } from 'file-saver'
import { collectionResource } from '../api'
import { useLog } from '@/composables/useLog'
const log = useLog()
const { query } = useRoute()
const courseId = $ref(query.course_id as string)
const chapterId = $ref(query.chapter_id as string)
const semesterId = $ref(query.semester_id as string)
const sectionId = $ref(query.section_id as string)
interface Props {
data: CourseResourceType
}
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&paper_title=${props.data.name}`
} else if (props.data.resource_type === 6) {
return info.join_url
} else {
return `/preview?course_id=${courseId}&semester_id=${semesterId}&resource_id=${props.data.resource_id}&resource_type=${props.data.resource_type}&url=${info.url}`
}
})
// 是否可以收藏
function canCollection(type: number) {
return [3, 4, 9, 10, 11].includes(type)
}
// 收藏/取消收藏
function toggleCollection(data: CourseResourceType) {
// 资源类型: 1章节,2视频,3作业,4其他,6腾讯会议,9考试,10课件,11教案
// 收藏类型: 1其他, 2视频,3课件,4教案,5作业,6帖子
const typeMap: Record<number, number> = { 4: 1, 2: 2, 10: 3, 11: 4, 3: 5, 9: 5 }
collectionResource({
course_id: courseId,
semester_id: semesterId,
chapter_id: chapterId,
section_id: sectionId,
source_id: data.resource_id,
type: typeMap[data.resource_type],
status: data.collection_count ? 0 : 1
}).then(() => {
data.collection_count = data.collection_count ? 0 : 1
})
}
// 是否可以下载
// function canDownload(type: number) {
// // return [4, 10, 11].includes(type)
// return [4].includes(type)
// }
// 下载资源
function downloadFile(data: CourseResourceType) {
const { url, name } = data.info
const urlExtensionName = url?.split('.').pop()
const nameExtensionName = name?.split('.').pop()
const filename = nameExtensionName === urlExtensionName ? name : `${name}.${urlExtensionName}`
url && saveAs(url, filename)
// 日志上送
log.upload({
event: 'file_event',
action: 'stu_download_file_action',
data: {
course_id: courseId,
resource_id: data.info.id,
resource_type: data.resource_type,
download_time: Math.floor(Date.now() / 1000),
download_name: name,
download_size: data.info.size
}
})
}
</script>
<template>
<div class="course-resource-item">
<p>
<a :href="targetUrl" target="_blank">
<ResourceIcon :resourceType="data.resource_type" :info="data.info" />
{{ data.info.name }}
</a>
</p>
<div class="actions">
<i
class="icon-star"
:class="!!data.collection_count ? 'is-active' : ''"
@click="toggleCollection(data)"
v-if="canCollection(data.resource_type)"
></i>
<i class="icon-download" @click="downloadFile(data)" v-if="!!data.can_download"><Download /></i>
</div>
</div>
</template>
<style lang="scss" scoped>
.course-resource-item {
display: flex;
align-items: center;
height: 48px;
padding: 0 20px;
border-bottom: 1px solid #e6e6e6;
p {
flex: 1;
line-height: 48px;
}
&:hover {
color: var(--main-color);
}
.actions {
min-width: 60px;
display: flex;
align-items: center;
justify-content: space-between;
&:empty {
min-width: auto;
}
}
}
.icon-star {
display: inline-block;
width: 16px;
height: 16px;
background: url(@/assets/images/icon_star.png) no-repeat;
background-size: contain;
cursor: pointer;
&.is-active {
background: url(@/assets/images/icon_star_hover.png) no-repeat;
background-size: contain;
}
}
.icon-download {
display: inline-block;
width: 20px;
height: 20px;
cursor: pointer;
}
</style>
...@@ -51,6 +51,7 @@ export interface CourseResourceType { ...@@ -51,6 +51,7 @@ export interface CourseResourceType {
depth: number depth: number
is_finished?: number is_finished?: number
paper_status?: number paper_status?: number
can_download: number
} }
export interface VideoRecordType { export interface VideoRecordType {
......
...@@ -9,6 +9,7 @@ const CourseViewWork = defineAsyncComponent(() => import('../components/CourseVi ...@@ -9,6 +9,7 @@ const CourseViewWork = defineAsyncComponent(() => import('../components/CourseVi
const CourseViewExam = defineAsyncComponent(() => import('../components/CourseViewExam.vue')) const CourseViewExam = defineAsyncComponent(() => import('../components/CourseViewExam.vue'))
const CourseViewAssess = defineAsyncComponent(() => import('../components/CourseViewAssess.vue')) const CourseViewAssess = defineAsyncComponent(() => import('../components/CourseViewAssess.vue'))
const CourseViewLive = defineAsyncComponent(() => import('../components/CourseViewLive.vue')) const CourseViewLive = defineAsyncComponent(() => import('../components/CourseViewLive.vue'))
const CourseViewMaterial = defineAsyncComponent(() => import('../components/CourseViewMaterial.vue'))
const { query } = useRoute() const { query } = useRoute()
const courseId = $ref<string | null>(query.course_id as string) const courseId = $ref<string | null>(query.course_id as string)
...@@ -133,6 +134,9 @@ function showInfo(title: string, content: string) { ...@@ -133,6 +134,9 @@ function showInfo(title: string, content: string) {
<el-tab-pane label="直播" lazy> <el-tab-pane label="直播" lazy>
<CourseViewLive /> <CourseViewLive />
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="资料" lazy>
<CourseViewMaterial />
</el-tab-pane>
</el-tabs> </el-tabs>
</div> </div>
</div> </div>
......
import type { CourseType, ResourceType } from '@/types' import type { CourseType, ChapterType, ResourceType } from '@/types'
export interface CollectionType { export interface CollectionType {
chapter_id: string chapter_id: string
...@@ -12,6 +12,9 @@ export interface CollectionType { ...@@ -12,6 +12,9 @@ export interface CollectionType {
status: number status: number
type: number type: number
resource_type: number resource_type: number
can_download: number
course: Pick<CourseType, 'id' | 'name' | 'course_id'>
chapter: Pick<ChapterType, 'id' | 'name'>
} }
export interface CollectionSemesterType { export interface CollectionSemesterType {
......
...@@ -74,10 +74,10 @@ function toggleCollection(data: CollectionType) { ...@@ -74,10 +74,10 @@ function toggleCollection(data: CollectionType) {
}) })
} }
// 是否可以下载 // 是否可以下载
function canDownload(type: number) { // function canDownload(type: number) {
// return [1, 3, 4].includes(type) // // return [1, 3, 4].includes(type)
return [1].includes(type) // return [1].includes(type)
} // }
// 下载资源 // 下载资源
function downloadFile(data: CollectionType) { function downloadFile(data: CollectionType) {
const { url, name } = data.info const { url, name } = data.info
...@@ -124,12 +124,15 @@ function targetUrl(item: CollectionType) { ...@@ -124,12 +124,15 @@ function targetUrl(item: CollectionType) {
{{ item.info.name || item.info.paper_title }} {{ item.info.name || item.info.paper_title }}
</router-link> </router-link>
</p> </p>
<p>{{ item.course.name }}/{{ item.chapter.name }}</p>
<div class="collection-item-aside">
<div class="video-duration" v-if="item.type === 2"> <div class="video-duration" v-if="item.type === 2">
{{ formatDuration(item.info.length) }} {{ formatDuration(item.info.length) }}
</div> </div>
<div class="actions"> <div class="actions">
<i class="icon-star" :class="!!item.status ? 'is-active' : ''" @click="toggleCollection(item)"></i> <i class="icon-star" :class="!!item.status ? 'is-active' : ''" @click="toggleCollection(item)"></i>
<i class="icon-download" @click="downloadFile(item)" v-if="canDownload(item.type)"><Download /></i> <i class="icon-download" @click="downloadFile(item)" v-if="!!item.can_download"><Download /></i>
</div>
</div> </div>
</li> </li>
</ul> </ul>
...@@ -146,6 +149,12 @@ function targetUrl(item: CollectionType) { ...@@ -146,6 +149,12 @@ function targetUrl(item: CollectionType) {
p { p {
flex: 1; flex: 1;
line-height: 48px; line-height: 48px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
p + p {
margin-left: 20px;
} }
&:hover { &:hover {
color: var(--main-color); color: var(--main-color);
...@@ -163,6 +172,12 @@ function targetUrl(item: CollectionType) { ...@@ -163,6 +172,12 @@ function targetUrl(item: CollectionType) {
line-height: 1; line-height: 1;
} }
} }
.collection-item-aside {
min-width: 200px;
display: flex;
align-items: center;
justify-content: flex-end;
}
.icon-star { .icon-star {
display: inline-block; display: inline-block;
width: 16px; width: 16px;
......
...@@ -84,6 +84,7 @@ export interface FileType { ...@@ -84,6 +84,7 @@ export interface FileType {
size: number size: number
source_id: string source_id: string
ppt_arr?: PptType[] ppt_arr?: PptType[]
can_download: number
} }
export interface PptType { export interface PptType {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论