123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- <!--
- * @Description: 课程视频
- * @Author: 空白格
- * @Date: 2022-08-24 13:48:47
- * @LastEditors: 空白格
- * @LastEditTime: 2022-12-16 11:53:22
- * @FilePath: \veterans_client_web\src\components\CourseVideo\index.vue
- * @Copyright: Copyright (c) 2016~2022 by 空白格, All Rights Reserved.
- -->
- <template>
- <div class="course-video">
- <div class="course-video-header">
- <div class="course-video-header-left">
- <div class="subtitle" v-if="courseDetails.major">
- {{ courseDetails.major || "-" }}
- </div>
- <div class="title">{{ currentClasses.chapterName || "-" }}</div>
- </div>
- <div class="course-video-header-right">
- 本课程 共{{ courseDetails.amount || 0 }}课,已学完{{
- courseDetails.finishCount || 0
- }}课,共进度{{ courseDetails.finishPercent || 0 }}%
- </div>
- </div>
- <div class="course-video-box">
- <el-row>
- <el-col :xs="24" :sm="24" :md="16" :lg="16" :xl="16">
- <div class="course-video-box-left" v-if="isPay">
- <video
- ref="video"
- id="myVideo"
- @timeupdate="timeUpdate"
- :src="currentClasses.videoUrl"
- controls
- :initial-time="videoInfo.initial_time"
- object-fit="fill"
- play-btn-position="center"
- @ended="ended"
- @click="videoClick"
- @loadedmetadata="loadedmetadata"
- ></video>
- </div>
- </el-col>
- <el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8">
- <div class="course-video-box-right">
- <div class="cvbr-top">
- <div class="cvbr-top-teacher">
- 主讲老师:{{ courseDetails.presenter || "-" }}
- </div>
- <div class="cvbr-top-des">
- {{ currentClasses.chapterInfo || "-" }}
- </div>
- </div>
- <div class="cvbr-bottom">
- <el-timeline class="cvbr-bottom-list">
- <el-timeline-item
- v-for="(course, index) in courseDetails.chapterList"
- :key="index"
- timestamp=""
- :color="course.id === currentClasses.id ? '#EF651F' : ''"
- >
- <div
- class="cvbr-bottom-list-item"
- :class="{ current: course.id === currentClasses.id }"
- @click="chooseClasses(course)"
- >
- 第{{ index + 1 }}课({{ course.finishPercent }}%)
- </div>
- </el-timeline-item>
- </el-timeline>
- </div>
- </div>
- </el-col>
- </el-row>
- </div>
- </div>
- </template>
- <script>
- import { submitClassesDuration } from "@/api/AdaptiveTraining";
- export default {
- name: "CourseVideoIndex",
- props: {
- courseDetails: {
- type: Object,
- default: () => {},
- },
- },
- data() {
- return {
- currentClasses: {},
- videoInfo: {
- initial_time: 0,
- duration: 0,
- playedTime: 0,
- video_real_time: 0,
- },
- isPay: false,
- };
- },
- watch: {
- "courseDetails.id"(val) {
- this.currentClasses = this.courseDetails.chapterList[0];
- this.videoInfo.playedTime =
- this.courseDetails.chapterList[0].playDuration;
- this.isPay = true;
- this.$nextTick(() => {
- let video = document.getElementById("myVideo");
- video.onpause = () => {
- this.submitVideoDuration();
- };
- });
- },
- },
- methods: {
- /**
- * 选择课程播放
- * @date 2022-08-24
- * @param {any} item
- * @returns {any}
- */
- chooseClasses(item) {
- this.isPay = false;
- this.submitVideoDuration(item, true);
- },
- /**
- * 视频播放实时触发
- * @date 2022-08-24
- * @param {any} e
- * @returns {any}
- */
- timeUpdate(e) {
- let detail = e.target;
- //播放的总时长
- let duration = detail.duration;
- //实时播放进度 秒数
- let jumpTime = parseInt(detail.currentTime);
- //当前视频进度
- if (jumpTime - this.videoInfo.playedTime > 3) {
- // 差别过大,调用seek方法跳转到实际观看时间
- this.$refs.video.currentTime = this.videoInfo.playedTime;
- this.$message.warning("未完整看完该视频,不能快进!");
- } else {
- this.videoInfo.video_real_time = parseInt(detail.currentTime);
- if (this.videoInfo.video_real_time > this.videoInfo.playedTime) {
- this.videoInfo.playedTime = this.videoInfo.video_real_time;
- }
- }
- },
- /**
- * 视频结束触发
- * @date 2022-08-24
- * @returns {any}
- */
- ended() {
- // this.submitVideoDuration();
- },
- /**
- * 视频点击触发
- * @date 2022-08-24
- * @param {any} e
- * @returns {any}
- */
- videoClick(e) {
- console.log(e);
- },
- /**
- * 视频加载完成触发
- * @date 2022-08-24
- * @param {any} details
- * @returns {any}
- */
- loadedmetadata(details) {
- this.videoInfo.duration = details.target.duration;
- this.videoInfo.initial_time = this.currentClasses.currentDuration;
- this.$nextTick(() => {
- this.$refs.video.currentTime = this.videoInfo.initial_time;
- });
- },
- /**
- * 提交视频播放进度
- * @date 2022-08-24
- * @returns {any}
- */
- submitVideoDuration(item, isNeed) {
- let playDuration = this.videoInfo.video_real_time,
- currentDuration = this.videoInfo.video_real_time;
- if (this.videoInfo.playDuration > this.videoInfo.video_real_time) {
- playDuration = this.videoInfo.playDuration;
- }
- // 防止视频未加载完成就提交
- if (Number(this.videoInfo.duration) > 0 && Number(playDuration) > 0) {
- submitClassesDuration({
- tabId: this.currentClasses.id,
- playDuration: playDuration,
- currentDuration: currentDuration,
- duration: this.videoInfo.duration,
- }).then((res) => {
- if (res.code === 200) {
- console.log("已记录播放时长" + JSON.stringify(res.data));
- if (isNeed) {
- this.$emit("changeClasses", item);
- this.currentClasses = item;
- this.isPay = true;
- this.videoInfo.playedTime = item.playDuration;
- this.videoInfo.initial_time = item.currentDuration;
- this.$nextTick(() => {
- let video = document.getElementById("myVideo");
- video.onpause = () => {
- this.submitVideoDuration();
- };
- });
- }
- }
- });
- }
- },
- },
- };
- </script>
- <style lang="scss" scoped>
- .course-video {
- padding: 10px 0 40px;
- &-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- color: #fff;
- padding: 10px 0;
- &-left {
- display: flex;
- align-items: center;
- .subtitle {
- padding: 7px 23px;
- background-color: #ef651f;
- font-size: 14px;
- border-radius: 20px;
- margin-right: 11px;
- }
- .title {
- font-size: 20px;
- line-height: 33px;
- }
- }
- &-right {
- font-size: 12px;
- line-height: 33px;
- }
- }
- &-box {
- width: 100%;
- &-left {
- width: 100%;
- video {
- width: 100%;
- background-color: #fff;
- aspect-ratio: 16 / 9;
- }
- }
- &-right {
- .cvbr-top {
- padding: 10px 25px;
- background: #4a5053;
- color: #fff;
- &-teacher {
- font-size: 20px;
- margin-bottom: 10px;
- }
- &-des {
- font-size: 14px;
- line-height: 25px;
- }
- }
- .cvbr-bottom {
- padding: 20px 30px;
- max-height: 40vh;
- overflow-y: auto;
- // &::-webkit-scrollbar {
- // width: 0;
- // }
- &-list {
- &-item {
- color: #fff;
- cursor: pointer;
- font-size: 14px;
- }
- .current {
- color: #ef651f;
- }
- }
- }
- }
- }
- }
- </style>
|