Browse Source

添加一个视频加载层

zaijin 2 years ago
parent
commit
00386536c2

+ 4 - 0
h5_web/main.js

@@ -7,6 +7,10 @@ Vue.prototype.config = config;
 
 import './utils/filter';
 
+// 使用v-loading
+import Loading from '@/utils/loading.js'
+Vue.use(Loading)
+
 App.mpType = 'app';
 
 // 引入全局uView

+ 371 - 341
h5_web/pages/basicTraining/onlineTrainingDetails/onlineTrainingDetails.vue

@@ -1,352 +1,382 @@
 <template>
-	<view class="details">
-		<u-navbar back-text="" title="" back-icon-color="#FFFFFF" :background="{ background: '#3D5D4C' }"
-			:border-bottom="false"></u-navbar>
-		<!-- 视频 -->
-		<view class="details-video" v-if="isPaly">
-			<video class="details-video-con" id="myVideo" @timeupdate="timeUpdate" :src="videoInfo.videoUrl" controls
-				:initial-time="initial_time" object-fit="fill" play-btn-position="center" @tap="videoClick"
-				@loadedmetadata="loadedmetadata">
-				<cover-view class="video-control">
-					<cover-view class="multi rate" @tap.stop="showSwitchRate">x {{ currentRate }}</cover-view>
-				</cover-view>
-				<cover-view class="multi-list rate" :class="{ active: rateShow }">
-					<cover-view v-for="(item, index) in ['0.5', '1.0', '1.5', '2.0']" :key="index"
-						class="multi-item rate" :data-rate="item" @tap="switchRate"
-						:class="{ active: item == currentRate }">
-						{{ item }}
-					</cover-view>
-				</cover-view>
-			</video>
-		</view>
-		<!-- 介绍 -->
-		<view class="details-content">
-			<view class="details-content-title">{{ videoInfo.chapterName }}</view>
-			<view class="details-content-progress">本课程
-				共{{ info.amount }}课,已学完{{ info.finishCount }}课,共进度{{ info.finishPercent || 0 }}%</view>
-			<view class="details-content-teacher">主讲老师:{{ info.presenter }}</view>
-			<view class="details-content-info">{{ videoInfo.chapterInfo }}</view>
-		</view>
+  <view class="details">
+    <u-navbar back-text="" title="" back-icon-color="#FFFFFF" :background="{ background: '#3D5D4C' }" :border-bottom="false"></u-navbar>
+    <!-- 视频 -->
+    <view class="details-video" v-if="isPaly" v-loading="videoLoading">
+      <video
+        class="details-video-con"
+        id="myVideo"
+        @timeupdate="timeUpdate"
+        :src="videoInfo.videoUrl"
+        controls
+        :initial-time="initial_time"
+        object-fit="fill"
+        play-btn-position="center"
+        @tap="videoClick"
+        @loadedmetadata="loadedmetadata"
+      >
+        <cover-view class="video-control">
+          <cover-view class="multi rate" @tap.stop="showSwitchRate">x {{ currentRate }}</cover-view>
+        </cover-view>
+        <cover-view class="multi-list rate" :class="{ active: rateShow }">
+          <cover-view
+            v-for="(item, index) in ['0.5', '1.0', '1.5', '2.0']"
+            :key="index"
+            class="multi-item rate"
+            :data-rate="item"
+            @tap="switchRate"
+            :class="{ active: item == currentRate }"
+          >
+            {{ item }}
+          </cover-view>
+        </cover-view>
+      </video>
+    </view>
+    <!-- 介绍 -->
+    <view class="details-content">
+      <view class="details-content-title">{{ videoInfo.chapterName }}</view>
+      <view class="details-content-progress">本课程 共{{ info.amount }}课,已学完{{ info.finishCount }}课,共进度{{ info.finishPercent || 0 }}%</view>
+      <view class="details-content-teacher">主讲老师:{{ info.presenter }}</view>
+      <view class="details-content-info">{{ videoInfo.chapterInfo }}</view>
+    </view>
 
-		<!-- 课程章节 -->
-		<view class="details-classes">
-			<view class="details-classes-header">
-				<view>精选课程</view>
-				<view>更多
-					<u-icon name="arrow-right" size="22" color="#A3A3A3" />
-				</view>
-			</view>
-			<view class="details-classes-list">
-				<view class="details-classes-list-item" v-for="(item, index) in info.chapterList" :key="index"
-					:class="{'active': index === videoIndex }" @click="classesClick(index)">
-					<view>{{ index + 1 }}</view>
-					<view>{{ item.flag === 2 ? '已学' : (item.finishPercent + '%') }}</view>
-				</view>
-			</view>
-		</view>
-		<view class="details-line">
-			<view></view>
-		</view>
-		<!-- 评论 -->
-		<view class="details-comment">
-			<view class="details-comment-header">
-				<view>课程评论</view>
-				<view>共{{ total }}条评论</view>
-			</view>
-			<view class="details-comment-list">
-				<view class="details-comment-list-item" v-for="(item, index) in commentList" :key="index">
-					<view class="left">
-						<u-avatar :src="item.createByAvatar" size="96" mode="square"></u-avatar>
-					</view>
-					<view class="right">
-						<view>{{ item.createBy }}</view>
-						<view>
-							<u-rate :count="5" size="28" disabled="" active-color="#FFBC00" v-model="item.starLevel">
-							</u-rate>
-							<text>{{ item.createTime }}</text>
-						</view>
-						<view>{{ item.content }}</view>
-					</view>
-				</view>
-			</view>
-			<view class="details-comment-page" v-if="total > 5">
-				<wyb-pagination :padding="0" :totalItems="total" :current="query.pageNum" @change="pageChange" />
-			</view>
+    <!-- 课程章节 -->
+    <view class="details-classes">
+      <view class="details-classes-header">
+        <view>精选课程</view>
+        <view
+          >更多
+          <u-icon name="arrow-right" size="22" color="#A3A3A3" />
+        </view>
+      </view>
+      <view class="details-classes-list">
+        <view
+          class="details-classes-list-item"
+          v-for="(item, index) in info.chapterList"
+          :key="index"
+          :class="{ active: index === videoIndex }"
+          @click="classesClick(index)"
+        >
+          <view>{{ index + 1 }}</view>
+          <view>{{ item.flag === 2 ? '已学' : item.finishPercent + '%' }}</view>
+        </view>
+      </view>
+    </view>
+    <view class="details-line">
+      <view></view>
+    </view>
+    <!-- 评论 -->
+    <view class="details-comment">
+      <view class="details-comment-header">
+        <view>课程评论</view>
+        <view>共{{ total }}条评论</view>
+      </view>
+      <view class="details-comment-list">
+        <view class="details-comment-list-item" v-for="(item, index) in commentList" :key="index">
+          <view class="left">
+            <u-avatar :src="item.createByAvatar" size="96" mode="square"></u-avatar>
+          </view>
+          <view class="right">
+            <view>{{ item.createBy }}</view>
+            <view>
+              <u-rate :count="5" size="28" disabled="" active-color="#FFBC00" v-model="item.starLevel"> </u-rate>
+              <text>{{ item.createTime }}</text>
+            </view>
+            <view>{{ item.content }}</view>
+          </view>
+        </view>
+      </view>
+      <view class="details-comment-page" v-if="total > 5">
+        <wyb-pagination :padding="0" :totalItems="total" :current="query.pageNum" @change="pageChange" />
+      </view>
 
-			<view class="details-comment-mine">
-				<text>我的评论</text>
-			</view>
+      <view class="details-comment-mine">
+        <text>我的评论</text>
+      </view>
 
-			<view class="details-comment-conent">
-				<view class="details-comment-conent-star">
-					<u-rate :count="5" size="40" active-color="#FFBC00" v-model="form.starLevel"></u-rate>
-				</view>
-				<view class="details-comment-content-textarea">
-					<u-input v-model="form.content" placeholder="请输入您的评价" type="textarea"
-						:custom-style="{ backgroundColor: '#F5F5F5', padding: '30rpx', borderRadius: '10rpx', minHeight: '280rpx' }">
-					</u-input>
-				</view>
-				<view class="details-comment-conent-button" @click="submitCommet">提交</view>
-			</view>
-		</view>
-		<u-toast ref="uToast" />
-	</view>
+      <view class="details-comment-conent">
+        <view class="details-comment-conent-star">
+          <u-rate :count="5" size="40" active-color="#FFBC00" v-model="form.starLevel"></u-rate>
+        </view>
+        <view class="details-comment-content-textarea">
+          <u-input
+            v-model="form.content"
+            placeholder="请输入您的评价"
+            type="textarea"
+            :custom-style="{ backgroundColor: '#F5F5F5', padding: '30rpx', borderRadius: '10rpx', minHeight: '280rpx' }"
+          >
+          </u-input>
+        </view>
+        <view class="details-comment-conent-button" @click="submitCommet">提交</view>
+      </view>
+    </view>
+    <u-toast ref="uToast" />
+  </view>
 </template>
 
 <script>
-	import wybPagination from '@/components/wyb-pagination/wyb-pagination.vue'
-	export default {
-		data() {
-			return {
-				info: {},
-				videoContext: uni.createVideoContext('myVideo', this),
-				videoInfo: {},
-				videoIndex: 0,
-				// 视频实时时间
-				initial_time: 0,
-				// 视频已经播放时间
-				playedTime: 0,
-				rateShow: false, // 倍速浮层
-				currentRate: 1.0, // 默认倍速
-				// 视频实际时间
-				video_real_time: 0,
-				classesId: '',
-				isPaly: true,
-				query: {
-					pageNum: 1,
-					pageSize: 5,
-					tabId: ''
-				},
-				total: 0,
-				commentList: [],
-				form: {
-					tabId: '',
-					starLevel: 0,
-					content: ''
-				},
-				currentDuration: 0,
-				duration: 0
-			}
-		},
-		onLoad(page) {
-			if (page.id) {
-				this.getClassesDetails(page.id);
-				this.classesId = page.id
-				this.query.tabId = this.classesId
-				this.form.tabId = this.classesId
-			}
-		},
-		beforeDestroy() {
-			this.confirmSubmitDuration();
-		},
-		methods: {
-			/**
-			 * 获取视频总时长
-			 * @param {Object} data
-			 */
-			loadedmetadata(data) {
-				this.duration = data.detail.duration;
-			},
-			/**
-			 * 显示倍速浮层
-			 * @param {Object} rate
-			 */
-			showSwitchRate(rate) {
-				let that = this;
-				that.rateShow = true;
-			},
-			/**
-			 * 切换倍速
-			 * @param {Object} e
-			 */
-			switchRate(e) {
-				let that = this;
-				let rate = Number(e.currentTarget.dataset.rate);
-				that.currentRate = rate;
-				that.rateShow = false;
-				this.videoContext.playbackRate(rate);
-			},
-			/**
-			 * 视频点击
-			 * @param {Object} e
-			 */
-			videoClick(e) {
-				this.rateShow = false;
-			},
-			/**
-			 * 获取课程详情
-			 * @param {Object} id
-			 */
-			getClassesDetails(id) {
-				this.$u.api.training.getOnlineDetailsApi({
-					id
-				}).then(res => {
-					if (res.code === 200) {
-						this.info = res.data;
-						this.videoInfo = res.data.chapterList[this.videoIndex];
-						this.initial_time = Number(res.data.chapterList[this.videoIndex].currentDuration)
-						this.video_real_time = Number(res.data.chapterList[this.videoIndex].playDuration)
-						this.playedTime = Number(res.data.chapterList[this.videoIndex].playDuration)
-						this.query.pageNum = 1;
-						this.isPaly = true
-						this.getCommentList();
-					}
-				})
-			},
-			/**
-			 * 课程章节点击
-			 * @param {Object} index
-			 */
-			classesClick(index) {
-				this.isPaly = false;
-				let playDuration = this.video_real_time;
-				if (this.videoInfo.playDuration > this.video_real_time) {
-					this.currentDuration = this.video_real_time;
-					playDuration = this.videoInfo.playDuration
-				} else {
-					this.currentDuration = this.video_real_time
-				}
-				this.submitTimeLong({
-					tabId: this.videoInfo.id,
-					playDuration: playDuration,
-					duration: this.duration,
-					currentDuration: this.currentDuration
-				}, index);
-			},
-			/**
-			 * 控制视频不能快进
-			 * @param {Object} e
-			 */
-			timeUpdate(e) {
-				//播放的总时长
-				let duration = e.detail.duration;
-				//实时播放进度 秒数
-				let jumpTime = parseInt(e.detail.currentTime);
-				//当前视频进度
-				if (jumpTime - this.playedTime > 3) {
-					// 差别过大,调用seek方法跳转到实际观看时间
-					this.videoContext.seek(this.playedTime);
-					wx.showToast({
-						title: '未完整看完该视频,不能快进',
-						icon: 'none',
-						duration: 2000
-					});
-				} else {
-					this.video_real_time = parseInt(e.detail.currentTime);
-					if (this.video_real_time > this.playedTime) {
-						this.playedTime = this.video_real_time;
-					}
-				}
-				if (parseInt(this.duration) !== 0 && parseInt(this.duration) === parseInt(this.video_real_time)) {
-					this.videoContext.pause();
-					this.confirmSubmitDuration()
-				}
-			},
-			/**
-			 * 提交课程时长
-			 */
-			submitTimeLong({
-				tabId,
-				playDuration,
-				duration,
-				currentDuration
-			}, index, flag) {
-				this.$u.api.training.videoTimeLongApi({
-					tabId,
-					playDuration,
-					duration,
-					currentDuration
-				}).then(res => {
-					if (res.code === 200) {
-						if (!flag) {
-							this.$refs.uToast.show({
-								title: '已记录章节时长!',
-								type: 'success'
-							})
-							this.videoInfo = this.info.chapterList[index]
-							this.videoIndex = index
-							this.getClassesDetails(this.classesId);
-						}
-					} else {
-						this.$refs.uToast.show({
-							title: res.msg,
-							type: 'error'
-						})
-					}
-				})
-			},
-			/**
-			 * 获取评论列表
-			 */
-			getCommentList() {
-				this.$u.api.training.getClassesCommentApi(this.query).then(res => {
-					if (res.code === 200) {
-						this.total = Number(res.total);
-						this.commentList = res.rows
-					}
-				})
-			},
-			/**
-			 * @param {Object} e 分页触发
-			 */
-			pageChange(e) {
-				this.query.pageNum = e.current
-				this.getCommentList()
-			},
-			/**
-			 * 提交评论
-			 */
-			submitCommet() {
-				if (this.form.starLevel && this.form.content) {
-					this.$u.api.training.addClassesCommentApi(this.form).then(res => {
-						if (res.code === 200) {
-							this.$refs.uToast.show({
-								title: '评论成功!',
-								type: 'success'
-							})
-							this.form.content = ''
-							this.form.starLevel = 0
-							this.getCommentList();
-						} else {
-							this.$refs.uToast.show({
-								title: res.msg,
-								type: 'error'
-							})
-						}
-					})
-				}
-				if (!this.form.starLevel) {
-					this.$refs.uToast.show({
-						title: '请选择星级',
-						type: 'warning'
-					})
-				}
-				if (!this.form.content) {
-					this.$refs.uToast.show({
-						title: '请输入评论内容',
-						type: 'warning'
-					})
-				}
-			},
-			confirmSubmitDuration() {
-				let playDuration = this.video_real_time;
-				if (this.videoInfo.playDuration > this.video_real_time) {
-					this.currentDuration = this.video_real_time;
-					playDuration = this.videoInfo.playDuration
-				} else {
-					this.currentDuration = this.video_real_time
-				}
-				this.submitTimeLong({
-					tabId: this.videoInfo.id,
-					playDuration: playDuration,
-					duration: this.duration,
-					currentDuration: this.currentDuration
-				}, 0, true)
-			}
-		}
-	}
+import wybPagination from '@/components/wyb-pagination/wyb-pagination.vue';
+export default {
+  data() {
+    return {
+      info: {},
+      videoContext: uni.createVideoContext('myVideo', this),
+      videoInfo: {},
+      videoIndex: 0,
+      // 视频实时时间
+      initial_time: 0,
+      // 视频已经播放时间
+      playedTime: 0,
+      rateShow: false, // 倍速浮层
+      currentRate: 1.0, // 默认倍速
+      // 视频实际时间
+      video_real_time: 0,
+      classesId: '',
+      isPaly: true,
+      query: {
+        pageNum: 1,
+        pageSize: 5,
+        tabId: ''
+      },
+      total: 0,
+      commentList: [],
+      form: {
+        tabId: '',
+        starLevel: 0,
+        content: ''
+      },
+      currentDuration: 0,
+      duration: 0,
+      videoLoading: false
+    };
+  },
+  onLoad(page) {
+    if (page.id) {
+      this.getClassesDetails(page.id);
+      this.classesId = page.id;
+      this.query.tabId = this.classesId;
+      this.form.tabId = this.classesId;
+    }
+  },
+  beforeDestroy() {
+    this.confirmSubmitDuration();
+  },
+  methods: {
+    /**
+     * 获取视频总时长
+     * @param {Object} data
+     */
+    loadedmetadata(data) {
+      this.duration = data.detail.duration;
+      this.videoLoading = false;
+    },
+    /**
+     * 显示倍速浮层
+     * @param {Object} rate
+     */
+    showSwitchRate(rate) {
+      let that = this;
+      that.rateShow = true;
+    },
+    /**
+     * 切换倍速
+     * @param {Object} e
+     */
+    switchRate(e) {
+      let that = this;
+      let rate = Number(e.currentTarget.dataset.rate);
+      that.currentRate = rate;
+      that.rateShow = false;
+      this.videoContext.playbackRate(rate);
+    },
+    /**
+     * 视频点击
+     * @param {Object} e
+     */
+    videoClick(e) {
+      this.rateShow = false;
+    },
+    /**
+     * 获取课程详情
+     * @param {Object} id
+     */
+    getClassesDetails(id) {
+      this.videoLoading = true;
+      this.$u.api.training
+        .getOnlineDetailsApi({
+          id
+        })
+        .then((res) => {
+          if (res.code === 200) {
+            this.info = res.data;
+            this.videoInfo = res.data.chapterList[this.videoIndex];
+            this.initial_time = Number(res.data.chapterList[this.videoIndex].currentDuration);
+            this.video_real_time = Number(res.data.chapterList[this.videoIndex].playDuration);
+            this.playedTime = Number(res.data.chapterList[this.videoIndex].playDuration);
+            this.query.pageNum = 1;
+            this.isPaly = true;
+            this.getCommentList();
+          }
+        });
+    },
+    /**
+     * 课程章节点击
+     * @param {Object} index
+     */
+    classesClick(index) {
+      this.isPaly = false;
+      let playDuration = this.video_real_time;
+      if (this.videoInfo.playDuration > this.video_real_time) {
+        this.currentDuration = this.video_real_time;
+        playDuration = this.videoInfo.playDuration;
+      } else {
+        this.currentDuration = this.video_real_time;
+      }
+      this.submitTimeLong(
+        {
+          tabId: this.videoInfo.id,
+          playDuration: playDuration,
+          duration: this.duration,
+          currentDuration: this.currentDuration
+        },
+        index
+      );
+    },
+    /**
+     * 控制视频不能快进
+     * @param {Object} e
+     */
+    timeUpdate(e) {
+      //播放的总时长
+      let duration = e.detail.duration;
+      //实时播放进度 秒数
+      let jumpTime = parseInt(e.detail.currentTime);
+      //当前视频进度
+      if (jumpTime - this.playedTime > 3) {
+        // 差别过大,调用seek方法跳转到实际观看时间
+        this.videoContext.seek(this.playedTime);
+        wx.showToast({
+          title: '未完整看完该视频,不能快进',
+          icon: 'none',
+          duration: 2000
+        });
+      } else {
+        this.video_real_time = parseInt(e.detail.currentTime);
+        if (this.video_real_time > this.playedTime) {
+          this.playedTime = this.video_real_time;
+        }
+      }
+      if (parseInt(this.duration) !== 0 && parseInt(this.duration) === parseInt(this.video_real_time)) {
+        this.videoContext.pause();
+        this.confirmSubmitDuration();
+      }
+    },
+    /**
+     * 提交课程时长
+     */
+    submitTimeLong({ tabId, playDuration, duration, currentDuration }, index, flag) {
+      this.$u.api.training
+        .videoTimeLongApi({
+          tabId,
+          playDuration,
+          duration,
+          currentDuration
+        })
+        .then((res) => {
+          if (res.code === 200) {
+            if (!flag) {
+              this.$refs.uToast.show({
+                title: '已记录章节时长!',
+                type: 'success'
+              });
+              this.videoInfo = this.info.chapterList[index];
+              this.videoIndex = index;
+              this.getClassesDetails(this.classesId);
+            }
+          } else {
+            this.$refs.uToast.show({
+              title: res.msg,
+              type: 'error'
+            });
+          }
+        });
+    },
+    /**
+     * 获取评论列表
+     */
+    getCommentList() {
+      this.$u.api.training.getClassesCommentApi(this.query).then((res) => {
+        if (res.code === 200) {
+          this.total = Number(res.total);
+          this.commentList = res.rows;
+        }
+      });
+    },
+    /**
+     * @param {Object} e 分页触发
+     */
+    pageChange(e) {
+      this.query.pageNum = e.current;
+      this.getCommentList();
+    },
+    /**
+     * 提交评论
+     */
+    submitCommet() {
+      if (this.form.starLevel && this.form.content) {
+        this.$u.api.training.addClassesCommentApi(this.form).then((res) => {
+          if (res.code === 200) {
+            this.$refs.uToast.show({
+              title: '评论成功!',
+              type: 'success'
+            });
+            this.form.content = '';
+            this.form.starLevel = 0;
+            this.getCommentList();
+          } else {
+            this.$refs.uToast.show({
+              title: res.msg,
+              type: 'error'
+            });
+          }
+        });
+      }
+      if (!this.form.starLevel) {
+        this.$refs.uToast.show({
+          title: '请选择星级',
+          type: 'warning'
+        });
+      }
+      if (!this.form.content) {
+        this.$refs.uToast.show({
+          title: '请输入评论内容',
+          type: 'warning'
+        });
+      }
+    },
+    confirmSubmitDuration() {
+      let playDuration = this.video_real_time;
+      if (this.videoInfo.playDuration > this.video_real_time) {
+        this.currentDuration = this.video_real_time;
+        playDuration = this.videoInfo.playDuration;
+      } else {
+        this.currentDuration = this.video_real_time;
+      }
+      this.submitTimeLong(
+        {
+          tabId: this.videoInfo.id,
+          playDuration: playDuration,
+          duration: this.duration,
+          currentDuration: this.currentDuration
+        },
+        0,
+        true
+      );
+    }
+  }
+};
 </script>
 
 <style lang="scss" scoped>
-	@import './onlineTrainingDetails.scss';
+@import './onlineTrainingDetails.scss';
 </style>

+ 7 - 0
h5_web/pages/skillsTraining/courseDetailed/courseDetailed.scss

@@ -263,4 +263,11 @@ page {
 }
 .multi-item.active {
 	color: #00d8ff;
+}
+.mask-loading {
+	width: 100%;
+	height: 100vh;
+	display: flex;
+	justify-content: center;
+	align-items: center;
 }

+ 401 - 380
h5_web/pages/skillsTraining/courseDetailed/courseDetailed.vue

@@ -1,389 +1,410 @@
 <template>
-	<view class="details">
-		<u-navbar back-text="" title="" back-icon-color="#FFFFFF" :background="{ background: '#3D5D4C' }"
-			:border-bottom="false"></u-navbar>
-		<!-- 视频 -->
-		<view class="details-video" v-if="isPlay">
-			<video class="details-video-con" id="myVideo" @timeupdate="timeUpdate" :src="videoInfo.videoUrl" controls
-				:initial-time="initial_time" object-fit="fill" play-btn-position="center" @ended="ended"
-				@tap="videoClick" @loadedmetadata="loadedmetadata">
-				<cover-view class="video-control">
-					<cover-view class="multi rate" @tap.stop="showSwitchRate">x {{ currentRate }}</cover-view>
-				</cover-view>
-				<cover-view class="multi-list rate" :class="{ active: rateShow }">
-					<cover-view v-for="(item, index) in ['0.5', '1.0', '1.5', '2.0']" :key="index"
-						class="multi-item rate" :data-rate="item" @tap="switchRate"
-						:class="{ active: item == currentRate }">
-						{{ item }}
-					</cover-view>
-				</cover-view>
-			</video>
-		</view>
-		<!-- 介绍 -->
-		<view class="details-content">
-			<view class="details-content-title">{{ videoInfo.chapterName }}</view>
-			<view class="details-content-progress">本课程
-				共{{ info.amount }}课,已学完{{ info.finishCount }}课,共进度{{ info.finishPercent || 0 }}%</view>
-			<view class="details-content-teacher">主讲老师:{{ info.presenter }}</view>
-			<view class="details-content-info">{{ videoInfo.chapterInfo }}</view>
-		</view>
+  <view class="details">
+    <u-navbar back-text="" title="" back-icon-color="#FFFFFF" :background="{ background: '#3D5D4C' }" :border-bottom="false"></u-navbar>
+    <!-- 视频 -->
+    <view class="details-video" v-if="isPlay" v-loading="videoLoading">
+      <video
+        class="details-video-con"
+        id="myVideo"
+        @timeupdate="timeUpdate"
+        :src="videoInfo.videoUrl"
+        controls
+        :initial-time="initial_time"
+        object-fit="fill"
+        play-btn-position="center"
+        @ended="ended"
+        @tap="videoClick"
+        @loadedmetadata="loadedmetadata"
+      >
+        <cover-view class="video-control">
+          <cover-view class="multi rate" @tap.stop="showSwitchRate">x {{ currentRate }}</cover-view>
+        </cover-view>
+        <cover-view class="multi-list rate" :class="{ active: rateShow }">
+          <cover-view
+            v-for="(item, index) in ['0.5', '1.0', '1.5', '2.0']"
+            :key="index"
+            class="multi-item rate"
+            :data-rate="item"
+            @tap="switchRate"
+            :class="{ active: item == currentRate }"
+          >
+            {{ item }}
+          </cover-view>
+        </cover-view>
+      </video>
+    </view>
+    <!-- 介绍 -->
+    <view class="details-content">
+      <view class="details-content-title">{{ videoInfo.chapterName || '-' }}</view>
+      <view class="details-content-progress"
+        >本课程 共{{ info.amount || 0 }}课,已学完{{ info.finishCount || 0 }}课,共进度{{ info.finishPercent || 0 }}%</view
+      >
+      <view class="details-content-teacher">主讲老师:{{ info.presenter || '-' }}</view>
+      <view class="details-content-info">{{ videoInfo.chapterInfo || '-' }}</view>
+    </view>
 
-		<!-- 课程章节 -->
-		<view class="details-classes">
-			<view class="details-classes-header">
-				<view>精选课程</view>
-				<view>
-					更多
-					<u-icon name="arrow-right" size="22" color="#A3A3A3" />
-				</view>
-			</view>
-			<view class="details-classes-list">
-				<view class="details-classes-list-item" v-for="(item, index) in info.chapterList" :key="index"
-					:class="{ active: index === videoIndex }" @click="classesClick(index)">
-					<view>{{ index + 1 }}</view>
-					<view>{{ item.flag === 2 ? '已学' : item.finishPercent + '%' }}</view>
-				</view>
-			</view>
-		</view>
-		<view class="details-line">
-			<view></view>
-		</view>
-		<!-- 评论 -->
-		<view class="details-comment">
-			<view class="details-comment-header">
-				<view>课程评论</view>
-				<view>共{{ total }}条评论</view>
-			</view>
-			<view class="details-comment-list">
-				<view class="details-comment-list-item" v-for="(item, index) in commentList" :key="index">
-					<view class="left">
-						<u-avatar :src="item.createByAvatar" size="96" mode="square"></u-avatar>
-					</view>
-					<view class="right">
-						<view>{{ item.createBy }}</view>
-						<view>
-							<u-rate :count="5" size="28" disabled="" active-color="#FFBC00" v-model="item.starLevel">
-							</u-rate>
-							<text>{{ item.createTime }}</text>
-						</view>
-						<view>{{ item.content }}</view>
-					</view>
-				</view>
-			</view>
-			<view class="details-comment-page" v-if="total">
-				<wyb-pagination :padding="0" :totalItems="total" :current="query.pageNum" @change="pageChange" />
-			</view>
-
-			<view class="details-comment-mine"><text>我的评论</text></view>
-
-			<view class="details-comment-conent">
-				<view class="details-comment-conent-star">
-					<u-rate :count="5" size="40" active-color="#FFBC00" v-model="form.starLevel"></u-rate>
-				</view>
-				<view class="details-comment-content-textarea">
-					<u-input v-model="form.content" placeholder="请输入您的评价" type="textarea"
-						:custom-style="{ backgroundColor: '#F5F5F5', padding: '30rpx', borderRadius: '10rpx', minHeight: '280rpx' }">
-					</u-input>
-				</view>
-				<view class="details-comment-conent-button" @click="submitCommet">提交</view>
-			</view>
-		</view>
-		<u-toast ref="uToast" />
-	</view>
+    <!-- 课程章节 -->
+    <view class="details-classes">
+      <view class="details-classes-header">
+        <view>精选课程</view>
+        <view>
+          更多
+          <u-icon name="arrow-right" size="22" color="#A3A3A3" />
+        </view>
+      </view>
+      <view class="details-classes-list">
+        <view
+          class="details-classes-list-item"
+          v-for="(item, index) in info.chapterList"
+          :key="index"
+          :class="{ active: index === videoIndex }"
+          @click="classesClick(index)"
+        >
+          <view>{{ index + 1 }}</view>
+          <view>{{ item.flag === 2 ? '已学' : item.finishPercent + '%' }}</view>
+        </view>
+      </view>
+    </view>
+    <view class="details-line">
+      <view></view>
+    </view>
+    <!-- 评论 -->
+    <view class="details-comment">
+      <view class="details-comment-header">
+        <view>课程评论</view>
+        <view>共{{ total || 0 }}条评论</view>
+      </view>
+      <view class="details-comment-list">
+        <view class="details-comment-list-item" v-for="(item, index) in commentList" :key="index">
+          <view class="left">
+            <u-avatar :src="item.createByAvatar" size="96" mode="square"></u-avatar>
+          </view>
+          <view class="right">
+            <view>{{ item.createBy }}</view>
+            <view>
+              <u-rate :count="5" size="28" disabled="" active-color="#FFBC00" v-model="item.starLevel"> </u-rate>
+              <text>{{ item.createTime }}</text>
+            </view>
+            <view>{{ item.content }}</view>
+          </view>
+        </view>
+      </view>
+      <view class="details-comment-page" v-if="total">
+        <wyb-pagination :padding="0" :totalItems="total" :current="query.pageNum" @change="pageChange" />
+      </view>
+      <view class="details-comment-mine"><text>我的评论</text></view>
+      <view class="details-comment-conent">
+        <view class="details-comment-conent-star">
+          <u-rate :count="5" size="40" active-color="#FFBC00" v-model="form.starLevel"></u-rate>
+        </view>
+        <view class="details-comment-content-textarea">
+          <u-input
+            v-model="form.content"
+            placeholder="请输入您的评价"
+            type="textarea"
+            :custom-style="{ backgroundColor: '#F5F5F5', padding: '30rpx', borderRadius: '10rpx', minHeight: '280rpx' }"
+          >
+          </u-input>
+        </view>
+        <view class="details-comment-conent-button" @click="submitCommet">提交</view>
+      </view>
+    </view>
+    <u-toast ref="uToast" />
+  </view>
 </template>
 
 <script>
-	import wybPagination from '@/components/wyb-pagination/wyb-pagination.vue';
-	export default {
-		data() {
-			return {
-				info: {},
-				videoContext: uni.createVideoContext('myVideo', this),
-				videoInfo: {},
-				videoIndex: 0,
-				// 视频实时时间
-				initial_time: 0,
-				// 视频已经播放时间
-				playedTime: 0,
-				rateShow: false, // 倍速浮层
-				currentRate: 1.0, // 默认倍速
-				// 视频实际时间
-				video_real_time: 0,
-				classesId: '',
-				isPlay: true,
-				query: {
-					pageNum: 1,
-					pageSize: 5,
-					tabId: ''
-				},
-				total: 0,
-				commentList: [],
-				form: {
-					tabId: '',
-					starLevel: 0,
-					content: ''
-				},
-				currentDuration: 0,
-				duration: 0,
-				isApply: 1
-			};
-		},
-		onLoad(page) {
-			if (page.id) {
-				this.getClassesDetails(page.id);
-				this.classesId = page.id;
-				this.query.tabId = this.classesId
-				this.form.tabId = this.classesId
-				this.isApply = page.isApply || 1
-			}
-		},
-		beforeDestroy() {
-			this.confirmSubmitDuration();
-		},
-		methods: {
-			/**
-			 * 获取视频总时长
-			 * @param {Object} data
-			 */
-			loadedmetadata(data) {
-				this.duration = data.detail.duration;
-			},
-			/**
-			 * 显示倍速浮层
-			 * @param {Object} rate
-			 */
-			showSwitchRate(rate) {
-				let that = this;
-				that.rateShow = true;
-			},
-			/**
-			 * 切换倍速
-			 * @param {Object} e
-			 */
-			switchRate(e) {
-				let that = this;
-				let rate = Number(e.currentTarget.dataset.rate);
-				that.currentRate = rate;
-				that.rateShow = false;
-				this.videoContext.playbackRate(rate);
-			},
-			/**
-			 * 视频点击
-			 * @param {Object} e
-			 */
-			videoClick(e) {
-				this.rateShow = false;
-			},
-			pause(e) {
-				console.log(e);
-			},
-			/**
-			 * 获取课程详情
-			 * @param {Object} id
-			 */
-			getClassesDetails(id) {
-				this.$u.api.school
-					.getPackageCourseDetail({
-						id
-					})
-					.then(res => {
-						if (res.code === 200) {
-							this.info = res.data;
-							this.videoInfo = res.data.chapterList[this.videoIndex];
-							this.initial_time = Number(res.data.chapterList[this.videoIndex].currentDuration);
-							this.video_real_time = Number(res.data.chapterList[this.videoIndex].playDuration);
-							this.playedTime = Number(res.data.chapterList[this.videoIndex].playDuration);
-							this.query.pageNum = 1;
-							this.isPlay = true;
-							this.getCommentList();
-						}
-					});
-			},
-			/**
-			 * 课程章节点击
-			 * @param {Object} index
-			 */
-			classesClick(index) {
-				this.isPlay = false;
-				let playDuration = this.video_real_time;
-				if (this.videoInfo.playDuration > this.video_real_time) {
-					this.currentDuration = this.video_real_time;
-					playDuration = this.videoInfo.playDuration;
-				} else {
-					this.currentDuration = this.video_real_time;
-				}
-				this.submitTimeLong({
-						tabId: this.videoInfo.id,
-						playDuration: playDuration,
-						duration: this.duration,
-						currentDuration: this.currentDuration
-					},
-					index
-				);
-			},
-			/**
-			 * 控制视频不能快进
-			 * @param {Object} e
-			 */
-			timeUpdate(e) {
-				//播放的总时长
-				let duration = e.detail.duration;
-				//实时播放进度 秒数
-				let jumpTime = parseInt(e.detail.currentTime);
-				//当前视频进度
-				if (jumpTime - this.playedTime > 3) {
-					// 差别过大,调用seek方法跳转到实际观看时间
-					this.videoContext.seek(this.playedTime);
-					wx.showToast({
-						title: '未完整看完该视频,不能快进',
-						icon: 'none',
-						duration: 2000
-					});
-				} else {
-					this.video_real_time = parseInt(e.detail.currentTime);
-					if (this.video_real_time > this.playedTime) {
-						this.playedTime = this.video_real_time;
-					}
-				}
-				if (parseInt(this.duration) !== 0 && parseInt(this.duration) === parseInt(this.video_real_time)) {
-					this.videoContext.pause();
-					this.confirmSubmitDuration();
-				}
-			},
-			/**
-			 * 视频结束
-			 */
-			ended() {
-				// 用户把进度条拉到最后,但是实际观看时间不够,跳转回去会自动暂停。
-				// 这里加个判断。
-				if (this.playedTime < this.duration) {
-					this.videoContext.play();
-					this.confirmSubmitDuration();
-				}
-			},
-			/**
-			 * 提交课程时长
-			 */
-			submitTimeLong({
-				tabId,
-				playDuration,
-				currentDuration,
-				duration
-			}, index, flag) {
-				if (tabId) {
-					this.$u.api.training
-						.videoTimeLongApi({
-							tabId,
-							playDuration,
-							currentDuration,
-							duration
-						})
-						.then(res => {
-							if (res.code === 200) {
-								if (!flag) {
-									this.$refs.uToast.show({
-										title: '已记录章节时长!',
-										type: 'success'
-									});
-									this.videoInfo = this.info.chapterList[index];
-									this.videoIndex = index;
-									this.getClassesDetails(this.classesId);
-								}
-							} else {
-								this.$refs.uToast.show({
-									title: res.msg,
-									type: 'error'
-								});
-							}
-						});
-				}
-			},
-			/**
-			 * 获取评论列表
-			 */
-			getCommentList() {
-				if (this.query.tabId) {
-					this.$u.api.training.getClassesCommentApi(this.query).then(res => {
-						if (res.code === 200) {
-							this.total = Number(res.total);
-							this.commentList = res.rows;
-						}
-					});
-				}
-			},
-			/**
-			 * @param {Object} e 分页触发
-			 */
-			pageChange(e) {
-				this.query.pageNum = e.current;
-				this.getCommentList();
-			},
-			/**
-			 * 提交评论
-			 */
-			submitCommet() {
-				if (this.form.tabId) {
-					if (this.form.starLevel && this.form.content) {
-						this.$u.api.training.addClassesCommentApi(this.form).then(res => {
-							if (res.code === 200) {
-								this.$refs.uToast.show({
-									title: '评论成功!',
-									type: 'success'
-								});
-								this.form.content = '';
-								this.form.starLevel = 0;
-								this.getCommentList();
-							} else {
-								this.$refs.uToast.show({
-									title: res.msg,
-									type: 'error'
-								});
-							}
-						});
-					}
-					if (!this.form.starLevel) {
-						this.$refs.uToast.show({
-							title: '请选择星级',
-							type: 'warning'
-						});
-					}
-					if (!this.form.content) {
-						this.$refs.uToast.show({
-							title: '请输入评论内容',
-							type: 'warning'
-						});
-					}
-				} else {
-					this.$refs.uToast.show({
-						title: '未找到课程章节,无法提交评论!',
-						type: 'warning'
-					});
-				}
-			},
-			confirmSubmitDuration() {
-				let playDuration = this.video_real_time;
-				if (this.videoInfo.playDuration > this.video_real_time) {
-					this.currentDuration = this.video_real_time;
-					playDuration = this.videoInfo.playDuration;
-				} else {
-					this.currentDuration = this.video_real_time;
-				}
-				if (Number(this.isApply) === 1) {
-					this.submitTimeLong({
-							tabId: this.videoInfo.id,
-							playDuration: playDuration,
-							currentDuration: this.currentDuration,
-							duration: this.duration
-						},
-						0,
-						true
-					);
-				}
-			}
-		}
-	};
+export default {
+  data() {
+    return {
+      info: {},
+      videoContext: uni.createVideoContext('myVideo', this),
+      videoInfo: {},
+      videoIndex: 0,
+      // 视频实时时间
+      initial_time: 0,
+      // 视频已经播放时间
+      playedTime: 0,
+      rateShow: false, // 倍速浮层
+      currentRate: 1.0, // 默认倍速
+      // 视频实际时间
+      video_real_time: 0,
+      classesId: '',
+      isPlay: true,
+      query: {
+        pageNum: 1,
+        pageSize: 5,
+        tabId: ''
+      },
+      total: 0,
+      commentList: [],
+      form: {
+        tabId: '',
+        starLevel: 0,
+        content: ''
+      },
+      currentDuration: 0,
+      duration: 0,
+      isApply: 1,
+      // 视频加载层
+      videoLoading: false
+    };
+  },
+  onLoad(page) {
+    if (page.id) {
+      this.getClassesDetails(page.id);
+      this.classesId = page.id;
+      this.query.tabId = this.classesId;
+      this.form.tabId = this.classesId;
+      this.isApply = page.isApply || 1;
+    }
+  },
+  beforeDestroy() {
+    this.confirmSubmitDuration();
+  },
+  methods: {
+    /**
+     * 获取视频总时长
+     * @param {Object} data
+     */
+    loadedmetadata(data) {
+      this.duration = data.detail.duration;
+      this.videoLoading = false;
+    },
+    /**
+     * 显示倍速浮层
+     * @param {Object} rate
+     */
+    showSwitchRate(rate) {
+      let that = this;
+      that.rateShow = true;
+    },
+    /**
+     * 切换倍速
+     * @param {Object} e
+     */
+    switchRate(e) {
+      let that = this;
+      let rate = Number(e.currentTarget.dataset.rate);
+      that.currentRate = rate;
+      that.rateShow = false;
+      this.videoContext.playbackRate(rate);
+    },
+    /**
+     * 视频点击
+     * @param {Object} e
+     */
+    videoClick(e) {
+      this.rateShow = false;
+    },
+    pause(e) {
+      console.log(e);
+    },
+    /**
+     * 获取课程详情
+     * @param {Object} id
+     */
+    getClassesDetails(id) {
+      this.videoLoading = true;
+      this.$u.api.school
+        .getPackageCourseDetail({
+          id
+        })
+        .then((res) => {
+          if (res.code === 200) {
+            this.info = res.data;
+            this.videoInfo = res.data.chapterList[this.videoIndex];
+            this.initial_time = Number(res.data.chapterList[this.videoIndex].currentDuration);
+            this.video_real_time = Number(res.data.chapterList[this.videoIndex].playDuration);
+            this.playedTime = Number(res.data.chapterList[this.videoIndex].playDuration);
+            this.query.pageNum = 1;
+            this.isPlay = true;
+            this.getCommentList();
+          }
+        });
+    },
+    /**
+     * 课程章节点击
+     * @param {Object} index
+     */
+    classesClick(index) {
+      this.isPlay = false;
+      let playDuration = this.video_real_time;
+      if (this.videoInfo.playDuration > this.video_real_time) {
+        this.currentDuration = this.video_real_time;
+        playDuration = this.videoInfo.playDuration;
+      } else {
+        this.currentDuration = this.video_real_time;
+      }
+      this.submitTimeLong(
+        {
+          tabId: this.videoInfo.id,
+          playDuration: playDuration,
+          duration: this.duration,
+          currentDuration: this.currentDuration
+        },
+        index
+      );
+    },
+    /**
+     * 控制视频不能快进
+     * @param {Object} e
+     */
+    timeUpdate(e) {
+      //播放的总时长
+      let duration = e.detail.duration;
+      //实时播放进度 秒数
+      let jumpTime = parseInt(e.detail.currentTime);
+      //当前视频进度
+      if (jumpTime - this.playedTime > 3) {
+        // 差别过大,调用seek方法跳转到实际观看时间
+        this.videoContext.seek(this.playedTime);
+        wx.showToast({
+          title: '未完整看完该视频,不能快进',
+          icon: 'none',
+          duration: 2000
+        });
+      } else {
+        this.video_real_time = parseInt(e.detail.currentTime);
+        if (this.video_real_time > this.playedTime) {
+          this.playedTime = this.video_real_time;
+        }
+      }
+      if (parseInt(this.duration) !== 0 && parseInt(this.duration) === parseInt(this.video_real_time)) {
+        this.videoContext.pause();
+        this.confirmSubmitDuration();
+      }
+    },
+    /**
+     * 视频结束
+     */
+    ended() {
+      // 用户把进度条拉到最后,但是实际观看时间不够,跳转回去会自动暂停。
+      // 这里加个判断。
+      if (this.playedTime < this.duration) {
+        this.videoContext.play();
+        this.confirmSubmitDuration();
+      }
+    },
+    /**
+     * 提交课程时长
+     */
+    submitTimeLong({ tabId, playDuration, currentDuration, duration }, index, flag) {
+      if (tabId) {
+        this.$u.api.training
+          .videoTimeLongApi({
+            tabId,
+            playDuration,
+            currentDuration,
+            duration
+          })
+          .then((res) => {
+            if (res.code === 200) {
+              if (!flag) {
+                this.$refs.uToast.show({
+                  title: '已记录章节时长!',
+                  type: 'success'
+                });
+                this.videoInfo = this.info.chapterList[index];
+                this.videoIndex = index;
+                this.getClassesDetails(this.classesId);
+              }
+            } else {
+              this.$refs.uToast.show({
+                title: res.msg,
+                type: 'error'
+              });
+            }
+          });
+      }
+    },
+    /**
+     * 获取评论列表
+     */
+    getCommentList() {
+      if (this.query.tabId) {
+        this.$u.api.training.getClassesCommentApi(this.query).then((res) => {
+          if (res.code === 200) {
+            this.total = Number(res.total);
+            this.commentList = res.rows;
+          }
+        });
+      }
+    },
+    /**
+     * @param {Object} e 分页触发
+     */
+    pageChange(e) {
+      this.query.pageNum = e.current;
+      this.getCommentList();
+    },
+    /**
+     * 提交评论
+     */
+    submitCommet() {
+      if (this.form.tabId) {
+        if (this.form.starLevel && this.form.content) {
+          this.$u.api.training.addClassesCommentApi(this.form).then((res) => {
+            if (res.code === 200) {
+              this.$refs.uToast.show({
+                title: '评论成功!',
+                type: 'success'
+              });
+              this.form.content = '';
+              this.form.starLevel = 0;
+              this.getCommentList();
+            } else {
+              this.$refs.uToast.show({
+                title: res.msg,
+                type: 'error'
+              });
+            }
+          });
+        }
+        if (!this.form.starLevel) {
+          this.$refs.uToast.show({
+            title: '请选择星级',
+            type: 'warning'
+          });
+        }
+        if (!this.form.content) {
+          this.$refs.uToast.show({
+            title: '请输入评论内容',
+            type: 'warning'
+          });
+        }
+      } else {
+        this.$refs.uToast.show({
+          title: '未找到课程章节,无法提交评论!',
+          type: 'warning'
+        });
+      }
+    },
+    confirmSubmitDuration() {
+      let playDuration = this.video_real_time;
+      if (this.videoInfo.playDuration > this.video_real_time) {
+        this.currentDuration = this.video_real_time;
+        playDuration = this.videoInfo.playDuration;
+      } else {
+        this.currentDuration = this.video_real_time;
+      }
+      if (Number(this.isApply) === 1) {
+        this.submitTimeLong(
+          {
+            tabId: this.videoInfo.id,
+            playDuration: playDuration,
+            currentDuration: this.currentDuration,
+            duration: this.duration
+          },
+          0,
+          true
+        );
+      }
+    }
+  }
+};
 </script>
 
 <style lang="scss" scoped>
-	@import './courseDetailed.scss';
+@import './courseDetailed.scss';
 </style>

+ 381 - 351
h5_web/pages/upgrade/courseDetail/courseDetail.vue

@@ -1,362 +1,392 @@
 <template>
-	<view class="details">
-		<!-- 视频 -->
-		<view class="details-video" v-if="isPaly">
-			<video class="details-video-con" id="myVideo" @timeupdate="timeUpdate" :src="videoInfo.videoUrl" controls
-				:initial-time="initial_time" object-fit="fill" play-btn-position="center" @tap="videoClick"
-				@loadedmetadata="loadedmetadata">
-				<cover-view class="video-control">
-					<cover-view class="multi rate" @tap.stop="showSwitchRate">x {{ currentRate }}</cover-view>
-				</cover-view>
-				<cover-view class="multi-list rate" :class="{ active: rateShow }">
-					<cover-view v-for="(item, index) in ['0.5', '1.0', '1.5', '2.0']" :key="index"
-						class="multi-item rate" :data-rate="item" @tap="switchRate"
-						:class="{ active: item == currentRate }">
-						{{ item }}
-					</cover-view>
-				</cover-view>
-			</video>
-		</view>
-		<!-- 介绍 -->
-		<view class="details-content">
-			<view class="details-content-title">{{ videoInfo.chapterName }}</view>
-			<view class="details-content-progress">本课程
-				共{{ info.amount }}课,已学完{{ info.finishCount }}课,共进度{{ info.finishPercent || 0 }}%</view>
-			<view class="details-content-teacher">主讲老师:{{ info.presenter }}</view>
-			<view class="details-content-info">{{ videoInfo.chapterInfo }}</view>
-		</view>
+  <view class="details">
+    <!-- 视频 -->
+    <view class="details-video" v-if="isPaly" v-loading="videoLoading">
+      <video
+        class="details-video-con"
+        id="myVideo"
+        @timeupdate="timeUpdate"
+        :src="videoInfo.videoUrl"
+        controls
+        :initial-time="initial_time"
+        object-fit="fill"
+        play-btn-position="center"
+        @tap="videoClick"
+        @loadedmetadata="loadedmetadata"
+      >
+        <cover-view class="video-control">
+          <cover-view class="multi rate" @tap.stop="showSwitchRate">x {{ currentRate }}</cover-view>
+        </cover-view>
+        <cover-view class="multi-list rate" :class="{ active: rateShow }">
+          <cover-view
+            v-for="(item, index) in ['0.5', '1.0', '1.5', '2.0']"
+            :key="index"
+            class="multi-item rate"
+            :data-rate="item"
+            @tap="switchRate"
+            :class="{ active: item == currentRate }"
+          >
+            {{ item }}
+          </cover-view>
+        </cover-view>
+      </video>
+    </view>
+    <!-- 介绍 -->
+    <view class="details-content">
+      <view class="details-content-title">{{ videoInfo.chapterName }}</view>
+      <view class="details-content-progress">本课程 共{{ info.amount }}课,已学完{{ info.finishCount }}课,共进度{{ info.finishPercent || 0 }}%</view>
+      <view class="details-content-teacher">主讲老师:{{ info.presenter }}</view>
+      <view class="details-content-info">{{ videoInfo.chapterInfo }}</view>
+    </view>
 
-		<!-- 课程章节 -->
-		<view class="details-classes">
-			<view class="details-classes-header">
-				<view>精选课程</view>
-				<view>更多
-					<u-icon name="arrow-right" size="22" color="#A3A3A3" />
-				</view>
-			</view>
-			<view class="details-classes-list">
-				<view class="details-classes-list-item" v-for="(item, index) in info.chapterList" :key="index"
-					:class="{'active': index === videoIndex }" @click="classesClick(index)">
-					<view>{{ index + 1 }}</view>
-					<view>{{ item.flag === 2 ? '已学' : (item.finishPercent + '%') }}</view>
-				</view>
-			</view>
-		</view>
-		<view class="details-line">
-			<view></view>
-		</view>
-		<!-- 评论 -->
-		<view class="details-comment">
-			<view class="details-comment-header">
-				<view>课程评论</view>
-				<view>共{{ total }}条评论</view>
-			</view>
-			<view class="details-comment-list">
-				<view class="details-comment-list-item" v-for="(item, index) in commentList" :key="index">
-					<view class="left">
-						<u-avatar :src="item.createByAvatar" size="96" mode="square"></u-avatar>
-					</view>
-					<view class="right">
-						<view>{{ item.createBy }}</view>
-						<view>
-							<u-rate :count="5" size="24" disabled="" active-color="#C4C4C4" v-model="item.starLevel">
-							</u-rate>
-							<text>{{ item.createTime }}</text>
-						</view>
-						<view>{{ item.content }}</view>
-					</view>
-				</view>
-			</view>
-			<view class="details-comment-page" v-if="total">
-				<wyb-pagination :padding="0" :totalItems="total" :current="query.pageNum" @change="pageChange" />
-			</view>
+    <!-- 课程章节 -->
+    <view class="details-classes">
+      <view class="details-classes-header">
+        <view>精选课程</view>
+        <view
+          >更多
+          <u-icon name="arrow-right" size="22" color="#A3A3A3" />
+        </view>
+      </view>
+      <view class="details-classes-list">
+        <view
+          class="details-classes-list-item"
+          v-for="(item, index) in info.chapterList"
+          :key="index"
+          :class="{ active: index === videoIndex }"
+          @click="classesClick(index)"
+        >
+          <view>{{ index + 1 }}</view>
+          <view>{{ item.flag === 2 ? '已学' : item.finishPercent + '%' }}</view>
+        </view>
+      </view>
+    </view>
+    <view class="details-line">
+      <view></view>
+    </view>
+    <!-- 评论 -->
+    <view class="details-comment">
+      <view class="details-comment-header">
+        <view>课程评论</view>
+        <view>共{{ total }}条评论</view>
+      </view>
+      <view class="details-comment-list">
+        <view class="details-comment-list-item" v-for="(item, index) in commentList" :key="index">
+          <view class="left">
+            <u-avatar :src="item.createByAvatar" size="96" mode="square"></u-avatar>
+          </view>
+          <view class="right">
+            <view>{{ item.createBy }}</view>
+            <view>
+              <u-rate :count="5" size="24" disabled="" active-color="#C4C4C4" v-model="item.starLevel"> </u-rate>
+              <text>{{ item.createTime }}</text>
+            </view>
+            <view>{{ item.content }}</view>
+          </view>
+        </view>
+      </view>
+      <view class="details-comment-page" v-if="total">
+        <wyb-pagination :padding="0" :totalItems="total" :current="query.pageNum" @change="pageChange" />
+      </view>
 
-			<view class="details-comment-mine">
-				<text>我的评论</text>
-			</view>
+      <view class="details-comment-mine">
+        <text>我的评论</text>
+      </view>
 
-			<view class="details-comment-conent">
-				<view class="details-comment-conent-star">
-					<u-rate :count="5" size="40" active-color="#FFBC00" v-model="form.starLevel"></u-rate>
-				</view>
-				<view class="details-comment-content-textarea">
-					<u-input v-model="form.content" placeholder="请输入您的评价" type="textarea"
-						:custom-style="{ backgroundColor: '#F5F5F5', padding: '30rpx', borderRadius: '10rpx', minHeight: '280rpx' }">
-					</u-input>
-				</view>
-				<view class="details-comment-conent-button" @click="submitCommet">提交</view>
-			</view>
-		</view>
-		<u-toast ref="uToast" />
-	</view>
+      <view class="details-comment-conent">
+        <view class="details-comment-conent-star">
+          <u-rate :count="5" size="40" active-color="#FFBC00" v-model="form.starLevel"></u-rate>
+        </view>
+        <view class="details-comment-content-textarea">
+          <u-input
+            v-model="form.content"
+            placeholder="请输入您的评价"
+            type="textarea"
+            :custom-style="{ backgroundColor: '#F5F5F5', padding: '30rpx', borderRadius: '10rpx', minHeight: '280rpx' }"
+          >
+          </u-input>
+        </view>
+        <view class="details-comment-conent-button" @click="submitCommet">提交</view>
+      </view>
+    </view>
+    <u-toast ref="uToast" />
+  </view>
 </template>
 
 <script>
-	import wybPagination from '@/components/wyb-pagination/wyb-pagination.vue'
-	export default {
-		data() {
-			return {
-				info: {},
-				videoContext: uni.createVideoContext('myVideo', this),
-				videoInfo: {},
-				videoIndex: 0,
-				// 视频实时时间
-				initial_time: 0,
-				// 视频已经播放时间
-				playedTime: 0,
-				rateShow: false, // 倍速浮层
-				currentRate: 1.0, // 默认倍速
-				// 视频实际时间
-				video_real_time: 0,
-				classesId: '',
-				isPaly: true,
-				query: {
-					pageNum: 1,
-					pageSize: 5,
-					tabId: ''
-				},
-				total: 0,
-				commentList: [],
-				form: {
-					tabId: '',
-					starLevel: 0,
-					content: ''
-				},
-				currentDuration: 0,
-				duration: 0
-			}
-		},
-		onLoad(page) {
-			if (page.id) {
-				this.getClassesDetails(page.id);
-				this.classesId = page.id
-				this.query.tabId = this.classesId
-				this.form.tabId = this.classesId
-			}
-		},
-		beforeDestroy() {
-			this.confirmSubmitDuration();
-		},
-		methods: {
-			/**
-			 * 获取视频总时长
-			 * @param {Object} data
-			 */
-			loadedmetadata(data) {
-				this.duration = data.detail.duration;
-			},
-			/**
-			 * 显示倍速浮层
-			 * @param {Object} rate
-			 */
-			showSwitchRate(rate) {
-				let that = this;
-				that.rateShow = true;
-			},
-			/**
-			 * 切换倍速
-			 * @param {Object} e
-			 */
-			switchRate(e) {
-				let that = this;
-				let rate = Number(e.currentTarget.dataset.rate);
-				that.currentRate = rate;
-				that.rateShow = false;
-				this.videoContext.playbackRate(rate);
-			},
-			/**
-			 * 视频点击
-			 * @param {Object} e
-			 */
-			videoClick(e) {
-				this.rateShow = false;
-			},
-			/**
-			 * 获取课程详情
-			 * @param {Object} id
-			 */
-			getClassesDetails(id) {
-				this.$u.api.school.getPackageCourseDetail({
-					id
-				}).then(res => {
-					if (res.code === 200) {
-						console.log(res)
-						this.info = res.data;
-						this.videoInfo = res.data.chapterList[this.videoIndex];
-						this.initial_time = Number(res.data.chapterList[this.videoIndex].currentDuration)
-						this.video_real_time = Number(res.data.chapterList[this.videoIndex].playDuration)
-						this.playedTime = Number(res.data.chapterList[this.videoIndex].playDuration)
-						this.query.pageNum = res.data.page;
-						this.isPaly = true
-						this.getCommentList();
-					}
-				})
-			},
-			/**
-			 * 课程章节点击
-			 * @param {Object} index
-			 */
-			classesClick(index) {
-				this.isPaly = false;
-				let playDuration = this.video_real_time;
-				if (this.videoInfo.playDuration > this.video_real_time) {
-					this.currentDuration = this.video_real_time;
-					playDuration = this.videoInfo.playDuration
-				} else {
-					this.currentDuration = this.video_real_time
-				}
-				this.submitTimeLong({
-					tabId: this.videoInfo.id,
-					playDuration: playDuration,
-					duration: this.duration,
-					currentDuration: this.currentDuration
-				}, index);
-			},
-			/**
-			 * 控制视频不能快进
-			 * @param {Object} e
-			 */
-			timeUpdate(e) {
-				//播放的总时长
-				let duration = e.detail.duration;
-				//实时播放进度 秒数
-				let jumpTime = parseInt(e.detail.currentTime);
-				//当前视频进度
-				if (jumpTime - this.playedTime > 3) {
-					// 差别过大,调用seek方法跳转到实际观看时间
-					this.videoContext.seek(this.playedTime);
-					wx.showToast({
-						title: '未完整看完该视频,不能快进',
-						icon: 'none',
-						duration: 2000
-					});
-				} else {
-					this.video_real_time = parseInt(e.detail.currentTime);
-					if (this.video_real_time > this.playedTime) {
-						this.playedTime = this.video_real_time;
-					}
-				}
-				if (parseInt(this.duration) !== 0 && parseInt(this.duration) === parseInt(this.video_real_time)) {
-					this.videoContext.pause();
-					this.confirmSubmitDuration()
-				}
-			},
-			/**
-			 * 提交课程时长
-			 */
-			submitTimeLong({
-				tabId,
-				playDuration,
-				duration,
-				currentDuration
-			}, index, flag) {
-				if (tabId) {
-					this.$u.api.training.videoTimeLongApi({
-						tabId,
-						playDuration,
-						duration,
-						currentDuration
-					}).then(res => {
-						if (res.code === 200) {
-							if (!flag) {
-								this.$refs.uToast.show({
-									title: '已记录章节时长!',
-									type: 'success'
-								})
-								this.videoInfo = this.info.chapterList[index]
-								this.videoIndex = index
-								this.getClassesDetails(this.classesId);
-							}
-						} else {
-							this.$refs.uToast.show({
-								title: res.msg,
-								type: 'error'
-							})
-						}
-					})
-				}
-			},
-			/**
-			 * 获取评论列表
-			 */
-			getCommentList() {
-				if (this.query.tabId) {
-					this.$u.api.training.getClassesCommentApi(this.query).then(res => {
-						if (res.code === 200) {
-							this.total = Number(res.total);
-							this.commentList = res.rows
-						}
-					})
-				}
-			},
-			/**
-			 * @param {Object} e 分页触发
-			 */
-			pageChange(e) {
-				this.query.pageNum = e.current
-				this.getCommentList()
-			},
-			/**
-			 * 提交评论
-			 */
-			submitCommet() {
-				if (this.form.tabId) {
-					if (this.form.starLevel && this.form.content) {
-						this.$u.api.training.addClassesCommentApi(this.form).then(res => {
-							if (res.code === 200) {
-								this.$refs.uToast.show({
-									title: '评论成功!',
-									type: 'success'
-								})
-								this.form.content = ''
-								this.form.starLevel = 0
-								this.getCommentList();
-							} else {
-								this.$refs.uToast.show({
-									title: res.msg,
-									type: 'error'
-								})
-							}
-						})
-					}
-					if (!this.form.starLevel) {
-						this.$refs.uToast.show({
-							title: '请选择星级',
-							type: 'warning'
-						})
-					}
-					if (!this.form.content) {
-						this.$refs.uToast.show({
-							title: '请输入评论内容',
-							type: 'warning'
-						})
-					}
-				} else {
-					this.$refs.uToast.show({
-						title: '未找到课程章节,无法提交评论!',
-						type: 'warning'
-					})
-				}
-			},
-			confirmSubmitDuration() {
-				let playDuration = this.video_real_time;
-				if (this.videoInfo.playDuration > this.video_real_time) {
-					this.currentDuration = this.video_real_time;
-					playDuration = this.videoInfo.playDuration
-				} else {
-					this.currentDuration = this.video_real_time
-				}
-				this.submitTimeLong({
-					tabId: this.videoInfo.id,
-					playDuration: playDuration,
-					duration: this.duration,
-					currentDuration: this.currentDuration
-				}, 0, true)
-			}
-		}
-	}
+export default {
+  data() {
+    return {
+      info: {},
+      videoContext: uni.createVideoContext('myVideo', this),
+      videoInfo: {},
+      videoIndex: 0,
+      // 视频实时时间
+      initial_time: 0,
+      // 视频已经播放时间
+      playedTime: 0,
+      rateShow: false, // 倍速浮层
+      currentRate: 1.0, // 默认倍速
+      // 视频实际时间
+      video_real_time: 0,
+      classesId: '',
+      isPaly: true,
+      query: {
+        pageNum: 1,
+        pageSize: 5,
+        tabId: ''
+      },
+      total: 0,
+      commentList: [],
+      form: {
+        tabId: '',
+        starLevel: 0,
+        content: ''
+      },
+      currentDuration: 0,
+      duration: 0,
+			videoLoading: false
+    };
+  },
+  onLoad(page) {
+    if (page.id) {
+      this.getClassesDetails(page.id);
+      this.classesId = page.id;
+      this.query.tabId = this.classesId;
+      this.form.tabId = this.classesId;
+    }
+  },
+  beforeDestroy() {
+    this.confirmSubmitDuration();
+  },
+  methods: {
+    /**
+     * 获取视频总时长
+     * @param {Object} data
+     */
+    loadedmetadata(data) {
+      this.duration = data.detail.duration;
+			this.videoLoading = false
+    },
+    /**
+     * 显示倍速浮层
+     * @param {Object} rate
+     */
+    showSwitchRate(rate) {
+      let that = this;
+      that.rateShow = true;
+    },
+    /**
+     * 切换倍速
+     * @param {Object} e
+     */
+    switchRate(e) {
+      let that = this;
+      let rate = Number(e.currentTarget.dataset.rate);
+      that.currentRate = rate;
+      that.rateShow = false;
+      this.videoContext.playbackRate(rate);
+    },
+    /**
+     * 视频点击
+     * @param {Object} e
+     */
+    videoClick(e) {
+      this.rateShow = false;
+    },
+    /**
+     * 获取课程详情
+     * @param {Object} id
+     */
+    getClassesDetails(id) {
+			this.videoLoading = true
+      this.$u.api.school
+        .getPackageCourseDetail({
+          id
+        })
+        .then((res) => {
+          if (res.code === 200) {
+            console.log(res);
+            this.info = res.data;
+            this.videoInfo = res.data.chapterList[this.videoIndex];
+            this.initial_time = Number(res.data.chapterList[this.videoIndex].currentDuration);
+            this.video_real_time = Number(res.data.chapterList[this.videoIndex].playDuration);
+            this.playedTime = Number(res.data.chapterList[this.videoIndex].playDuration);
+            this.query.pageNum = res.data.page;
+            this.isPaly = true;
+            this.getCommentList();
+          }
+        });
+    },
+    /**
+     * 课程章节点击
+     * @param {Object} index
+     */
+    classesClick(index) {
+      this.isPaly = false;
+      let playDuration = this.video_real_time;
+      if (this.videoInfo.playDuration > this.video_real_time) {
+        this.currentDuration = this.video_real_time;
+        playDuration = this.videoInfo.playDuration;
+      } else {
+        this.currentDuration = this.video_real_time;
+      }
+      this.submitTimeLong(
+        {
+          tabId: this.videoInfo.id,
+          playDuration: playDuration,
+          duration: this.duration,
+          currentDuration: this.currentDuration
+        },
+        index
+      );
+    },
+    /**
+     * 控制视频不能快进
+     * @param {Object} e
+     */
+    timeUpdate(e) {
+      //播放的总时长
+      let duration = e.detail.duration;
+      //实时播放进度 秒数
+      let jumpTime = parseInt(e.detail.currentTime);
+      //当前视频进度
+      if (jumpTime - this.playedTime > 3) {
+        // 差别过大,调用seek方法跳转到实际观看时间
+        this.videoContext.seek(this.playedTime);
+        wx.showToast({
+          title: '未完整看完该视频,不能快进',
+          icon: 'none',
+          duration: 2000
+        });
+      } else {
+        this.video_real_time = parseInt(e.detail.currentTime);
+        if (this.video_real_time > this.playedTime) {
+          this.playedTime = this.video_real_time;
+        }
+      }
+      if (parseInt(this.duration) !== 0 && parseInt(this.duration) === parseInt(this.video_real_time)) {
+        this.videoContext.pause();
+        this.confirmSubmitDuration();
+      }
+    },
+    /**
+     * 提交课程时长
+     */
+    submitTimeLong({ tabId, playDuration, duration, currentDuration }, index, flag) {
+      if (tabId) {
+        this.$u.api.training
+          .videoTimeLongApi({
+            tabId,
+            playDuration,
+            duration,
+            currentDuration
+          })
+          .then((res) => {
+            if (res.code === 200) {
+              if (!flag) {
+                this.$refs.uToast.show({
+                  title: '已记录章节时长!',
+                  type: 'success'
+                });
+                this.videoInfo = this.info.chapterList[index];
+                this.videoIndex = index;
+                this.getClassesDetails(this.classesId);
+              }
+            } else {
+              this.$refs.uToast.show({
+                title: res.msg,
+                type: 'error'
+              });
+            }
+          });
+      }
+    },
+    /**
+     * 获取评论列表
+     */
+    getCommentList() {
+      if (this.query.tabId) {
+        this.$u.api.training.getClassesCommentApi(this.query).then((res) => {
+          if (res.code === 200) {
+            this.total = Number(res.total);
+            this.commentList = res.rows;
+          }
+        });
+      }
+    },
+    /**
+     * @param {Object} e 分页触发
+     */
+    pageChange(e) {
+      this.query.pageNum = e.current;
+      this.getCommentList();
+    },
+    /**
+     * 提交评论
+     */
+    submitCommet() {
+      if (this.form.tabId) {
+        if (this.form.starLevel && this.form.content) {
+          this.$u.api.training.addClassesCommentApi(this.form).then((res) => {
+            if (res.code === 200) {
+              this.$refs.uToast.show({
+                title: '评论成功!',
+                type: 'success'
+              });
+              this.form.content = '';
+              this.form.starLevel = 0;
+              this.getCommentList();
+            } else {
+              this.$refs.uToast.show({
+                title: res.msg,
+                type: 'error'
+              });
+            }
+          });
+        }
+        if (!this.form.starLevel) {
+          this.$refs.uToast.show({
+            title: '请选择星级',
+            type: 'warning'
+          });
+        }
+        if (!this.form.content) {
+          this.$refs.uToast.show({
+            title: '请输入评论内容',
+            type: 'warning'
+          });
+        }
+      } else {
+        this.$refs.uToast.show({
+          title: '未找到课程章节,无法提交评论!',
+          type: 'warning'
+        });
+      }
+    },
+    confirmSubmitDuration() {
+      let playDuration = this.video_real_time;
+      if (this.videoInfo.playDuration > this.video_real_time) {
+        this.currentDuration = this.video_real_time;
+        playDuration = this.videoInfo.playDuration;
+      } else {
+        this.currentDuration = this.video_real_time;
+      }
+      this.submitTimeLong(
+        {
+          tabId: this.videoInfo.id,
+          playDuration: playDuration,
+          duration: this.duration,
+          currentDuration: this.currentDuration
+        },
+        0,
+        true
+      );
+    }
+  }
+};
 </script>
 
 <style lang="scss" scoped>
-	@import './courseDetail.scss';
+@import './courseDetail.scss';
 </style>

+ 76 - 0
h5_web/static/css/loading.scss

@@ -0,0 +1,76 @@
+/deep/ .el-loading-parent--relative {
+  position: relative !important;
+}
+
+/deep/ .el-loading-mask {
+  position: absolute;
+  z-index: 2000;
+  background-color: rgba(0, 0, 0, 0.8);
+  margin: 0;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  transition: opacity 0.3s;
+
+  .el-loading-spinner {
+    top: 50%;
+    margin-top: -21px;
+    width: 100%;
+    text-align: center;
+    position: absolute;
+  }
+
+  .el-loading-spinner .el-loading-text {
+    color: #409eff;
+    margin: 3px 0;
+    font-size: 14px;
+  }
+
+  .el-loading-spinner .circular {
+    height: 42px;
+    width: 42px;
+    animation: loading-rotate 2s linear infinite;
+  }
+
+  .el-loading-spinner .path {
+    animation: loading-dash 1.5s ease-in-out infinite;
+    stroke-dasharray: 90, 150;
+    stroke-dashoffset: 0;
+    stroke-width: 2;
+    stroke: #409eff;
+    stroke-linecap: round;
+  }
+
+  .el-loading-spinner i {
+    color: #409eff;
+  }
+
+  .el-loading-fade-enter,
+  .el-loading-fade-leave-active {
+    opacity: 0;
+  }
+
+  @keyframes loading-rotate {
+    to {
+      transform: rotate(1turn);
+    }
+  }
+
+  @keyframes loading-dash {
+    0% {
+      stroke-dasharray: 1, 200;
+      stroke-dashoffset: 0;
+    }
+
+    50% {
+      stroke-dasharray: 90, 150;
+      stroke-dashoffset: -40px;
+    }
+
+    to {
+      stroke-dasharray: 90, 150;
+      stroke-dashoffset: -120px;
+    }
+  }
+}

+ 1 - 0
h5_web/uni.scss

@@ -4,3 +4,4 @@
  * uView自定义的css类名和scss变量,均以"u-"开头,不会造成冲突,请放心使用 
  */
 @import 'uview-ui/theme.scss';
+@import '/static/css/loading.scss';

+ 53 - 0
h5_web/utils/loading.js

@@ -0,0 +1,53 @@
+import Vue from 'vue';
+
+/**
+ * 插入loading
+ */
+const insertDom = (el) => {
+  let dom = `<div class="el-loading-mask">
+        <div class="el-loading-spinner">
+          <svg viewBox="25 25 50 50" class="circular">
+            <circle cx="50" cy="50" r="20" fill="none" class="path"> </circle>
+          </svg>
+          <p class="el-loading-text">拼命加载中...</p>
+        </div>
+      </div>`;
+
+  //el添加相对定位
+  el.classList.add('el-loading-parent--relative');
+
+  // 插入到被绑定的元素内部
+  el.insertAdjacentHTML('afterbegin', dom);
+};
+
+/**
+ * 移除loading
+ */
+const removeDom = (el) => {
+  const ds = el.getElementsByClassName('el-loading-mask')[0];
+  if (ds) {
+    el.removeChild(ds);
+    el.classList.remove('el-loading-parent--relative');
+  }
+};
+
+// 更新是否显示
+const toggleLoading = (el, binding) => {
+  if (binding.value) {
+    insertDom(el);
+  } else {
+    removeDom(el);
+  }
+};
+
+Vue.directive('loading', {
+  bind: function (el, binding, vnode) {
+    toggleLoading(el, binding);
+  },
+  //所在组件的 VNode 更新时调用--比较更新前后的值
+  update: function (el, binding) {
+    if (binding.oldValue !== binding.value) {
+      toggleLoading(el, binding);
+    }
+  }
+});