优化倍数播放

This commit is contained in:
binbin_pan 2024-12-25 14:27:22 +08:00
parent 689d2017d4
commit 480225f049
6 changed files with 121 additions and 262 deletions

View File

@ -50,7 +50,7 @@
</div> </div>
<view class="no-task" v-show="!taskList || taskList.length === 0"> <view class="no-task" v-show="!taskList || taskList.length === 0">
<view class="no-task-img"> <view class="no-task-img">
<image src="/static/eduImg/no-task.png"></image> <image src="/static/eduImg/no-task.png" style="width: 179px; height: 94px;"></image>
<span>可联系管理员发布</span> <span>可联系管理员发布</span>
</view> </view>
</view> </view>

View File

@ -1,97 +0,0 @@
<template>
<view>
<div class="video">
<video
id="myVideo"
:src="videoUrl"
:initial-time="videoInitialTime"
:show-progress="false"
:enable-progress-gesture="false"
@error="videoErrorCallback"
@timeupdate="videoTimeUpdate"
/>
</div>
<u-modal :show="showModal" title="提示" :content='content' showCancelButton @cancel="showModal = false" @confirm="handleEnd" />
<div class="btn">
<u-button type="primary" shape="circle" text="结束学习" size="small" @click="openModal" />
</div>
</view>
</template>
<script>
export default {
props: {
states: {
type: Object,
default: () => {}
}
},
data() {
return {
videoInitialTime: 0, //
//
currentTime: 0,
videoUrl: '',
content: '是否确认结束学习?',
showModal: false
}
},
mounted() {
console.log('🚀 ~ mounted ~ this.states:', this.states)
this.videoInitialTime = this.states.initialTime
this.videoUrl = this.states.url
},
methods: {
videoErrorCallback(e) {
console.log('视频错误信息:', e)
},
//
videoTimeUpdate(e) {
console.log('视频播放时间:', e.detail.currentTime)
this.currentTime = Math.floor(e.detail.currentTime)
},
openModal() {
this.showModal = true
},
//
handleEnd() {
this.$verificationToken()
this.showModal = false
//
const video = uni.createVideoContext('myVideo')
video.pause()
// -
console.log('当前播放时间:', this.currentTime)
this.$emit('handleVideo', this.currentTime)
}
}
}
</script>
<style lang="scss" scoped>
// video
::v-deep .uni-video-controls {
display: none !important;
}
.video {
width: 100%;
height: 260px;
uni-video {
width: 100%;
height: 100%;
}
}
.btn {
margin: 60px auto;
width: 100px;
}
::v-deep .u-modal__content {
flex-direction: column;
align-items: center;
}
</style>

View File

@ -1,81 +0,0 @@
<template>
<view>
<VideoStudy :states="states" @handleVideo="handleVideo" />
<!-- <div class="content">
<div v-for="(item, index) in studyList" :key="index" @click="handleStudyItem(item)">
<ListItem :states="item" />
</div>
</div> -->
</view>
</template>
<script>
import VideoStudy from './components/VideoStudy'
import ListItem from './components/ListItem'
export default {
components: { VideoStudy, ListItem },
data() {
return {
showVideo: false,
states: {
initialTime: 70, //
url: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/2minute-demo.mp4'
},
//
studyList: [
{
id: 1,
//
studyTitle: '送配电线路架设(初级)',
//
progress: 30,
//
duration: '00:12:00',
initialTime: 12,
url: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/2minute-demo.mp4'
},
{
id: 2,
studyTitle: '送配电线路架设(中级)',
progress: 50,
duration: '00:12:00',
initialTime: 12,
url: 'http://qp118.bmwae.cn/preview/file?pageCount=4&file_type=pdf&id=1117542&url=https%3A%2F%2Fbmwfileres.bmwax.cn%2Fmqrcode%2Fmqrfile%2F586413%2F1723517907_3080034644_%E6%B5%8B%E8%AF%95.pdf&preview_url=convert%2Fmqrcode%2Fmqrfile%2F586413%2F1723517907_3080034644_%E6%B5%8B%E8%AF%95&short=xmQqgA&domain=w.afbcs.cn&sign=&d=true&t=%E6%B5%8B%E8%AF%95&tips='
},
{
id: 3,
studyTitle: '送配电线路架设(高级)',
progress: 70,
duration: '00:12:00',
initialTime: 12,
url: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/2minute-demo.mp4'
}
]
}
},
methods: {
handleVideo(val) {
console.log('🚀 ~ handleVideo ~ val:', val)
this.showVideo = false
},
handleStudyItem(item) {
console.log('🚀 ~ handleStudyItem ~ item:', item, item.url.includes('.pdf'))
if (item.url.includes('.pdf')) {
uni.navigateTo({
url: '/pages/YNEduApp/learn/pdfStudy',
})
} else {
this.states = item
this.showVideo = true
}
}
}
}
</script>
<style lang="scss" scoped>
.content {
padding: 10px;
}
</style>

View File

@ -5,10 +5,28 @@
id="myVideo" id="myVideo"
:src="path" :src="path"
:initial-time="studyDuration" :initial-time="studyDuration"
:show-progress="true"
:enable-progress-gesture="false"
@error="videoErrorCallback" @error="videoErrorCallback"
@timeupdate="videoTimeUpdate" @timeupdate="videoTimeUpdate"
controls controls
/> >
<cover-view v-if="showCoverView" style="position: absolute; top: 28px; right: 20px; color: #fff; z-index: 999">
<cover-view @tap="showSwitchRate">x {{ currentRate }}</cover-view>
</cover-view>
<cover-view v-if="rateShow" class="multi-list rate" :class="{ active: rateShow }">
<cover-view
v-for="(item, index) in ['0.5', '0.8', '1.0', '1.25', '1.5']"
:key="index"
class="multi-item rate"
:data-rate="item"
@tap="switchRate"
:class="{ active: item == currentRate }"
>
{{ item }}
</cover-view>
</cover-view>
</video>
</div> </div>
<u-modal <u-modal
@ -60,7 +78,10 @@ export default {
isHide: false, isHide: false,
oldTime: 0, oldTime: 0,
// //
failCount: 3 failCount: 3,
rateShow: false, //
currentRate: 1.0, //
showCoverView: true
} }
}, },
onLoad(opt) { onLoad(opt) {
@ -80,6 +101,9 @@ export default {
if (opt.isEnd) { if (opt.isEnd) {
this.studyDuration = 0 this.studyDuration = 0
} }
if (opt.isSpeed == '0') {
this.showCoverView = false
}
this.video = uni.createVideoContext('myVideo') this.video = uni.createVideoContext('myVideo')
this.$verificationToken() this.$verificationToken()
}, },
@ -98,12 +122,37 @@ export default {
} }
}, },
methods: { methods: {
onFullScreenChange(e) {
console.log('🚀 ~ 全屏了 ~ e:', e)
},
//
showSwitchRate(rate) {
let that = this
console.log('rateShow', rate)
this.$nextTick(() => {
that.rateShow = true
})
console.log('rateShow', that.rateShow)
},
//
switchRate(e) {
let that = this
let rate = Number(e.currentTarget.dataset.rate)
that.currentRate = rate
that.rateShow = false
this.video.playbackRate(rate)
},
videoErrorCallback(e) { videoErrorCallback(e) {
console.log('视频错误信息:', e) console.log('视频错误信息:', e)
}, },
// //
videoTimeUpdate(e) { videoTimeUpdate(e) {
let newTime = Math.ceil(e.detail.currentTime) let newTime = Math.ceil(e.detail.currentTime)
if (Math.abs(newTime - this.currentTime) > 1.5) {
console.log('手动拖动了进度条,重置时间到上传播放时间')
this.video.seek(this.currentTime)
return
}
if (this.currentTime != newTime) { if (this.currentTime != newTime) {
this.currentTime = newTime this.currentTime = newTime
console.log('🚀 ~ 视频播放时间: ~ this.currentTime:', this.currentTime) console.log('🚀 ~ 视频播放时间: ~ this.currentTime:', this.currentTime)
@ -235,10 +284,10 @@ export default {
} */ } */
.video { .video {
width: 100vw; width: 100%;
height: 260px; height: 260px;
uni-video { uni-video {
width: 100vw; width: 100%;
height: 100%; height: 100%;
} }
} }
@ -248,8 +297,68 @@ export default {
width: 100px; width: 100px;
} }
::v-deep .u-modal__content { /* ::v-deep .u-modal__content {
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
} */
/* 以下为视频CSS */
.multi-list.full-screen.vertical {
height: 100vh !important;
padding: 8vh 0;
} }
.multi-list.full-screen.horizontal {
height: 100vw !important;
padding: 8vw 0;
}
.multi {
position: absolute;
right: 30rpx;
top: 50%;
transform: translateY(-50%);
z-index: 999998;
width: 100rpx;
color: #fff;
padding: 10rpx 0;
text-align: center;
transition: color ease 0.3s;
}
.multi.rate {
right: 30rpx;
}
.multi-list {
position: absolute;
height: 100%;
width: 0;
background-color: rgba(0, 0, 0, 0.65);
top: 0;
right: 0;
transition: width 0.3s ease;
z-index: 999999;
box-sizing: border-box;
padding: 50rpx 0;
}
.multi-list.rate {
padding: 25rpx 0;
}
.multi-list.active {
width: 300rpx;
}
.multi-item {
text-align: center;
color: #fff;
line-height: 80rpx;
transition: color ease 0.3s;
}
.multi-item.rate {
line-height: 70rpx;
}
.multi-item:hover,
.multi:hover {
color: #00d8ff;
}
.multi-item.active {
color: #00d8ff;
}
/* 视频CSS结束 */
</style> </style>

View File

@ -9,16 +9,6 @@
<div :class="{ 'tab-line': activeIndex === index }"></div> <div :class="{ 'tab-line': activeIndex === index }"></div>
</div> </div>
</div> </div>
<!-- <view class="status-secs">
<view
v-for="(item, index) in statusList"
:key="item.id"
:class="[{ active: totalStatus.statusCount === item.id }]"
@click="chooseStatus(item.id)"
>
{{ item.text }}
</view>
</view> -->
<uni-easyinput <uni-easyinput
suffixIcon="search" suffixIcon="search"
v-model="totalStatus.keyword" v-model="totalStatus.keyword"
@ -30,7 +20,7 @@
<view class="project-cont"> <view class="project-cont">
<view v-for="(item, index) in projList" :key="item.id" class="single-proj" @click="toggleDetail(item.id)"> <view v-for="(item, index) in projList" :key="item.id" class="single-proj" @click="toggleDetail(item.id)">
<h4 class="img"> <h4 class="img">
<image src="/static/images/studyPro.png"></image> <image src="../../../static/images/studyPro.png"></image>
</h4> </h4>
<view class="proj-detail"> <view class="proj-detail">
<view class="detail-upper"> <view class="detail-upper">
@ -110,71 +100,6 @@ export default {
], ],
// //
projList: [] projList: []
// projList: [
// {
// id: 1,
// img: 'https://cdn.uviewui.com/uview/swiper/1.jpg',
// title: '',
// star: 5,
// avatar: '/static/eduImg/avatar.jpg',
// user: '',
// percent: 71
// },
// {
// id: 2,
// img: 'https://cdn.uviewui.com/uview/swiper/1.jpg',
// title: '',
// star: 3,
// avatar: '/static/eduImg/avatar.jpg',
// user: '',
// percent: 33
// },
// {
// id: 3,
// img: 'https://cdn.uviewui.com/uview/swiper/1.jpg',
// title: '',
// star: 2,
// avatar: '/static/eduImg/avatar.jpg',
// user: '',
// percent: 94
// },
// {
// id: 4,
// img: 'https://cdn.uviewui.com/uview/swiper/1.jpg',
// title: '',
// star: 4,
// avatar: '/static/eduImg/avatar.jpg',
// user: '',
// percent: 76
// },
// {
// id: 5,
// img: 'https://cdn.uviewui.com/uview/swiper/1.jpg',
// title: '',
// star: 1,
// avatar: '/static/eduImg/avatar.jpg',
// user: '',
// percent: 63
// },
// {
// id: 6,
// img: 'https://cdn.uviewui.com/uview/swiper/1.jpg',
// title: '',
// star: 5,
// avatar: '/static/eduImg/avatar.jpg',
// user: '',
// percent: 52
// },
// {
// id: 7,
// img: 'https://cdn.uviewui.com/uview/swiper/1.jpg',
// title: '',
// star: 4,
// avatar: '/static/eduImg/avatar.jpg',
// user: '',
// percent: 18
// }
// ]
} }
}, },
mounted() { mounted() {

View File

@ -153,7 +153,8 @@ export default {
eligibility: 0, eligibility: 0,
learnIconObj: { color: '#1A63AC', size: '18', type: 'calendar' }, learnIconObj: { color: '#1A63AC', size: '18', type: 'calendar' },
pracIconObj: { color: '#38B022', size: '18', type: 'compose' }, pracIconObj: { color: '#38B022', size: '18', type: 'compose' },
listStage: [] listStage: [],
isSpeed: ''
} }
}, },
onLoad(params) { onLoad(params) {
@ -188,6 +189,7 @@ export default {
this.listStageContentNum = res.data.listStageContentNum this.listStageContentNum = res.data.listStageContentNum
this.eligibility = res.data.eligibility this.eligibility = res.data.eligibility
this.listStage = res.data.listStage this.listStage = res.data.listStage
this.isSpeed = res.data.isSpeed
if (this.listStage.length > 0) { if (this.listStage.length > 0) {
this.listStage.forEach((item, index) => { this.listStage.forEach((item, index) => {
this.$set(item, 'isShow', true) this.$set(item, 'isShow', true)
@ -210,7 +212,8 @@ export default {
path: item.path, // path: item.path, //
studyDuration: item.studyDuration || 0, // studyDuration: item.studyDuration || 0, //
allStudyDuration: item.allStudyDuration, // allStudyDuration: item.allStudyDuration, //
isEnd: item.studyPercentage >= 100 ? true : false isEnd: item.studyPercentage >= 100 ? true : false,
isSpeed: this.isSpeed
} }
console.log('🚀 ~ toggleTheoryLearn ~ params:', params) console.log('🚀 ~ toggleTheoryLearn ~ params:', params)
console.log('🚀 ~ toggleTheoryLearn ~ item:', item.path) console.log('🚀 ~ toggleTheoryLearn ~ item:', item.path)