|
@@ -1,27 +1,227 @@
|
|
|
<template>
|
|
|
- <view>asdfsdfas</view>
|
|
|
+ <view class="course-container">
|
|
|
+ <!-- 视频播放器 -->
|
|
|
+ <video v-if="currentVideo.url" :src="currentVideo.url" :id="videoId" controls @ended="handleVideoEnd"
|
|
|
+ @timeupdate="handleTimeUpdate" @loadedmetadata="handleVideoLoaded">
|
|
|
+ </video>
|
|
|
+
|
|
|
+ <!-- 课程信息 -->
|
|
|
+ <view class="course-header">
|
|
|
+ <text class="course-title">测试课程1</text>
|
|
|
+ <view class="course-meta">
|
|
|
+ <text>讲师:张老师</text>
|
|
|
+ <text>时长:3分42秒</text>
|
|
|
+ <text>1人学习</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 选项卡 -->
|
|
|
+ <view class="course-tabs">
|
|
|
+ <text :class="['tab-item', activeTab === '目录' ? 'active' : '']" @click="activeTab = '目录'">目录</text>
|
|
|
+ <text :class="['tab-item', activeTab === '介绍' ? 'active' : '']" @click="activeTab = '介绍'">介绍</text>
|
|
|
+ <text :class="['tab-item', activeTab === '评论' ? 'active' : '']" @click="activeTab = '评论'">评论</text>
|
|
|
+ <text :class="['tab-item', activeTab === '考试' ? 'active' : '']" @click="activeTab = '考试'">考试</text>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 目录内容 -->
|
|
|
+ <view v-if="activeTab === '目录'" class="course-content">
|
|
|
+ <catalogue ref="catalogueRef" @kejianInfo='getKejianInfo' :options="kejianUserVo"
|
|
|
+ :current-video="currentVideo"></catalogue>
|
|
|
+
|
|
|
+ </view>
|
|
|
+
|
|
|
+ </view>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
import {
|
|
|
- getKechengList
|
|
|
- } from "@/api/course.js";
|
|
|
+ ref,
|
|
|
+ onMounted
|
|
|
+ } from 'vue';
|
|
|
import {
|
|
|
onLoad,
|
|
|
- onReady
|
|
|
+ onReady,
|
|
|
+
|
|
|
} from "@dcloudio/uni-app"
|
|
|
import {
|
|
|
- reactive,
|
|
|
- ref
|
|
|
- } from "vue";
|
|
|
+ kechengStart
|
|
|
+ } from "@/api/course.js";
|
|
|
+ import catalogue from './common/catalogue.vue';
|
|
|
+ // 选项卡状态
|
|
|
+ const activeTab = ref('');
|
|
|
+ let kcId = ref('');
|
|
|
+ let kejianUserVo = ref(null);
|
|
|
+ // 当前播放信息
|
|
|
+ const currentVideo = ref({
|
|
|
+ url: '',
|
|
|
+ kjId: ''
|
|
|
+ });
|
|
|
+ const currentChapter = ref(0);
|
|
|
+ const currentSection = ref(0);
|
|
|
+ const catalogueRef = ref(null);
|
|
|
+ const videoId = ref('courseVideo');
|
|
|
+ let videoContext = null;
|
|
|
onLoad((options) => {
|
|
|
- console.log('options',options);
|
|
|
+ console.log('options', options);
|
|
|
+ kcId.value = options.kcId
|
|
|
+ getKechengData()
|
|
|
+ });
|
|
|
+ onMounted(() => {
|
|
|
+
|
|
|
});
|
|
|
- const kechengClick = ()=>{
|
|
|
+
|
|
|
+ function getKechengData() {
|
|
|
+ kechengStart({
|
|
|
+ kcId: kcId.value
|
|
|
+ }).then(res => {
|
|
|
+ console.log('res', res);
|
|
|
+ kejianUserVo.value = res.data.kejianUserVo
|
|
|
+ activeTab.value = '目录'
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ function getKejianInfo(data) {
|
|
|
+ console.log('data', data);
|
|
|
+ // currentVideo.value = {
|
|
|
+ // url: data.url || 'https://www.w3school.com.cn/example/html5/mov_bbb.mp4',
|
|
|
+ // kjId: data.kjId
|
|
|
+ // };
|
|
|
+ currentVideo.value = {
|
|
|
+ url: 'https://www.w3school.com.cn/example/html5/mov_bbb.mp4',
|
|
|
+ kjId: data.kjId
|
|
|
+ };
|
|
|
|
|
|
+ setTimeout(() => {
|
|
|
+ if (!videoContext) {
|
|
|
+ videoContext = uni.createVideoContext(videoId.value, this);
|
|
|
+ }
|
|
|
+ const cachedTime = uni.getStorageSync(`video_${data.kjId}`) || 0;
|
|
|
+ videoContext.seek(cachedTime);
|
|
|
+ }, 300);
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+ const handleTimeUpdate = (e) => {
|
|
|
+ const currentTime = e.detail.currentTime;
|
|
|
+ uni.setStorageSync(`video_${currentVideo.value.kjId}`, currentTime);
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleVideoEnd = () => {
|
|
|
+ catalogueRef.value.playNextVideo();
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleVideoLoaded = (e) => {
|
|
|
+ uni.setStorageSync(`duration_${currentVideo.value.kjId}`, e.detail.duration);
|
|
|
+ };
|
|
|
</script>
|
|
|
|
|
|
-<style lang="scss">
|
|
|
+<style scoped>
|
|
|
+ .course-container {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ height: 100vh;
|
|
|
+ }
|
|
|
+
|
|
|
+ .course-header {
|
|
|
+ padding: 20rpx;
|
|
|
+ background: #f5f5f5;
|
|
|
+ }
|
|
|
+
|
|
|
+ .course-title {
|
|
|
+ font-size: 36rpx;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+
|
|
|
+ .course-meta {
|
|
|
+ margin-top: 10rpx;
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #666;
|
|
|
+ }
|
|
|
+
|
|
|
+ .course-tabs {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-around;
|
|
|
+ padding: 20rpx;
|
|
|
+ background: #fff;
|
|
|
+ border-bottom: 1rpx solid #ddd;
|
|
|
+ }
|
|
|
+
|
|
|
+ .tab-item {
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #666;
|
|
|
+ }
|
|
|
+
|
|
|
+ .tab-item.active {
|
|
|
+ color: #09BB07;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+
|
|
|
+ .course-content {
|
|
|
+ flex: 1;
|
|
|
+ overflow-y: auto;
|
|
|
+ padding: 20rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .chapter-list {
|
|
|
+ background: #fff;
|
|
|
+ }
|
|
|
+
|
|
|
+ .chapter-item {
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .chapter-title {
|
|
|
+ padding: 20rpx;
|
|
|
+ background: #f5f5f5;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ border-bottom: 1rpx solid #ddd;
|
|
|
+ }
|
|
|
+
|
|
|
+ .section-list {
|
|
|
+ background: #fff;
|
|
|
+ }
|
|
|
+
|
|
|
+ .section-item {
|
|
|
+ padding: 20rpx;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ border-bottom: 1rpx solid #eee;
|
|
|
+ }
|
|
|
+
|
|
|
+ .section-info {
|
|
|
+ flex: 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ .section-title {
|
|
|
+ display: block;
|
|
|
+ font-size: 28rpx;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+
|
|
|
+ .play-status {
|
|
|
+ width: 180rpx;
|
|
|
+ text-align: right;
|
|
|
+ }
|
|
|
|
|
|
+ .playing {
|
|
|
+ color: #09BB07;
|
|
|
+ font-size: 24rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .progress {
|
|
|
+ color: #666;
|
|
|
+ font-size: 24rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ .unplayed {
|
|
|
+ color: #999;
|
|
|
+ font-size: 24rpx;
|
|
|
+ }
|
|
|
+
|
|
|
+ video {
|
|
|
+ width: 100%;
|
|
|
+ height: 300rpx;
|
|
|
+ background: #000;
|
|
|
+ }
|
|
|
</style>
|