123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- <template>
- <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 v-if="activeTab == '介绍'" class="course-content">
- <view v-if="!kechengData.intro" class="s-kehceng-default">
- <view>
- <img :src="jieshaoImg">
- <text>还没有介绍</text>
- </view>
- </view>
- <view v-else v-html="kechengData.intro" class="kecheng-tab-jieshao"></view>
- </view>
- </view>
- </template>
- <script setup>
- import {
- ref,
- onMounted
- } from 'vue';
- import {
- onLoad,
- onReady,
- } from "@dcloudio/uni-app"
- import {
- kechengStart
- } from "@/api/course.js";
- import catalogue from './common/catalogue.vue';
- // 选项卡状态
- const activeTab = ref('');
- let kcId = ref('');
- let kejianUserVo = ref(null);
- let jieshaoImg = ref('/static/images/kecheng/kecheng-introduce.svg');
- let kechengData = 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);
- kcId.value = options.kcId
- });
- onMounted(() => {
- getKechengData()
- });
- function getKechengData() {
- kechengStart({
- kcId: kcId.value
- }).then(res => {
- console.log('res', res);
- activeTab.value = '目录'
- kejianUserVo.value = res.data.kejianUserVo
- kechengData.value = res.data
- })
- }
- function getKejianInfo(data) {
- console.log('data', data.url);
- currentVideo.value = {
- url: data.url,
- 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 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>
|