120 lines
4.9 KiB
Vue
120 lines
4.9 KiB
Vue
<template>
|
||
<view class="scroll-container theme-light">
|
||
<view class="bt-page" v-if="course">
|
||
<MemberInfoSubNav title="线上课程" @back="onBack" />
|
||
<image class="mi-detail-hero" :src="course.cover" mode="aspectFill" />
|
||
<view class="bt-page__body">
|
||
<view class="bt-card">
|
||
<text class="bt-card__title">{{ course.title }}</text>
|
||
<text class="bt-card__desc">时长 {{ course.duration }} · 进度 {{ course.progress }}%</text>
|
||
<view class="mi-mod-course-card__progress" style="margin-top:12px;">
|
||
<view class="mi-mod-course-card__progress-bar">
|
||
<view class="mi-mod-course-card__progress-fill" :style="{ width: course.progress + '%' }"></view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="bt-card">
|
||
<text class="bt-card__title">视频播放</text>
|
||
<view class="mi-online-player">
|
||
<image class="mi-online-player__play" src="/static/images/play.png" mode="aspectFit" />
|
||
<text class="mi-online-player__hint">点击播放(支持倍速与拖拽)</text>
|
||
</view>
|
||
<view class="mi-online-controls">
|
||
<text class="mi-online-controls__btn" @tap="seek(-10)">-10s</text>
|
||
<text class="mi-online-controls__btn" @tap="togglePlay">{{ playing ? '暂停' : '播放' }}</text>
|
||
<text class="mi-online-controls__btn" @tap="seek(10)">+10s</text>
|
||
<text class="mi-online-controls__btn" @tap="changeSpeed">倍速 {{ speed }}x</text>
|
||
</view>
|
||
</view>
|
||
<view class="bt-card">
|
||
<text class="bt-card__title">课程目录</text>
|
||
<view v-for="ch in course.chapters" :key="ch.id" class="mi-online-chapter">
|
||
<text class="mi-online-chapter__title">{{ ch.title }}</text>
|
||
<text class="mi-online-chapter__meta">{{ ch.duration }} · {{ ch.done ? '已学完' : '未学习' }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import MemberInfoSubNav from '@/components/memberInfo/MemberInfoSubNav.vue'
|
||
import { PAGE, goBackOrTab } from '@/common/constants/routes.js'
|
||
import { loadMemberStore, persistMemberStore } from '@/common/memberInfo/store.js'
|
||
import { getOnlineCourseById, updateOnlineProgress } from '@/common/memberInfo/moduleStore.js'
|
||
|
||
export default {
|
||
components: { MemberInfoSubNav },
|
||
data() {
|
||
return { course: null, playing: false, speed: 1 }
|
||
},
|
||
onLoad(options) {
|
||
this.course = getOnlineCourseById(loadMemberStore(), options?.id)
|
||
},
|
||
methods: {
|
||
onBack() { goBackOrTab(PAGE.MY_COURSES) },
|
||
togglePlay() {
|
||
this.playing = !this.playing
|
||
if (this.playing && this.course.progress < 100) {
|
||
const store = loadMemberStore()
|
||
updateOnlineProgress(store, this.course.id, Math.min(100, this.course.progress + 5))
|
||
persistMemberStore(store)
|
||
this.course.progress = Math.min(100, this.course.progress + 5)
|
||
}
|
||
},
|
||
seek(sec) { uni.showToast({ title: `跳转 ${sec > 0 ? '+' : ''}${sec}s`, icon: 'none' }) },
|
||
changeSpeed() {
|
||
const speeds = [1, 1.25, 1.5, 2]
|
||
const idx = (speeds.indexOf(this.speed) + 1) % speeds.length
|
||
this.speed = speeds[idx]
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style>
|
||
@import '@/common/style/base.css';
|
||
@import '@/common/style/memberInfo/pages/page-reset.css';
|
||
@import '@/common/style/memberInfo/pages/sub-page-base.css';
|
||
@import '@/common/style/memberInfo/member-info-component-reset.css';
|
||
@import '@/common/style/memberInfo/member-info-sub-nav.css';
|
||
@import '@/common/style/memberInfo/pages/body-test-common.css';
|
||
@import '@/common/style/memberInfo/pages/module-pages-common.css';
|
||
|
||
.mi-online-player {
|
||
height: 180px;
|
||
border-radius: 12px;
|
||
background: #000;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.mi-online-player__play { width: 48px; height: 48px; }
|
||
.mi-online-player__hint { font-size: 12px; color: rgba(255,255,255,0.7); }
|
||
|
||
.mi-online-controls {
|
||
display: flex;
|
||
flex-direction: row;
|
||
justify-content: space-around;
|
||
margin-top: 12px;
|
||
}
|
||
|
||
.mi-online-controls__btn {
|
||
font-size: 12px;
|
||
color: var(--primary-deep, #1A4A6F);
|
||
font-weight: 600;
|
||
}
|
||
|
||
.mi-online-chapter {
|
||
padding: 10px 0;
|
||
border-bottom: 1px solid var(--border-light, #E9EDF2);
|
||
}
|
||
|
||
.mi-online-chapter__title { font-size: 14px; color: var(--text-dark, #1E2A3A); display: block; }
|
||
.mi-online-chapter__meta { font-size: 11px; color: var(--text-muted, #5E6F8D); }
|
||
</style>
|