<template>
|
<view>
|
<!-- 课程封面 -->
|
<view class="course-thumb">
|
<u-image :src="course.thumb" mode="aspectFill" :lazy-load="true"></u-image>
|
</view>
|
<!-- 课程介绍 -->
|
<view class="course-info">
|
<view class="course-title">
|
{{course.title}}
|
</view>
|
<view class="justify-between group_2">
|
<view class="flex-row">
|
<text class="text_2">¥{{(course.charge / 100) || 0}}</text>
|
<text class="text_3">¥{{(course.charge_original / 100) || 0}}</text>
|
</view>
|
<text class="text_4">共{{videoNum}}节课</text>
|
</view>
|
<view class="vip-tip" v-if="course.free_roles&&course.free_roles.length>0">
|
<u-icon name="level" color="#FCA128" size="28"></u-icon>{{transVipRole(course.free_roles)}}可免费学习此课程
|
</view>
|
</view>
|
<view class="course-tabs">
|
<u-tabs-swiper ref="uTabs" active-color="#FF4B4B" :list="list" :current="current" @change="tabsChange"
|
:is-scroll="false" swiperWidth="750"></u-tabs-swiper>
|
</view>
|
<swiper duration="200" class="swiper-item-box" :current="swiperCurrent" @transition="transition"
|
@animationfinish="animationfinish">
|
<swiper-item class="swiper-item">
|
<scroll-view :scroll-y="scrollFlag">
|
<mp-html :content="course.render_desc"></mp-html>
|
</scroll-view>
|
</swiper-item>
|
<swiper-item class="swiper-item">
|
<scroll-view :scroll-y="scrollFlag">
|
<view class="chapters">
|
<block v-if="chapterList && chapterList.length > 0">
|
<u-collapse event-type="close" :arrow="true" :accordion="false">
|
<u-collapse-item :index="index" :title="item.title" v-for="(item, index) in chapterList"
|
:key="item._id" :class="{study_status_all: canShowVideo(item)}">
|
<view class="collapse-item" v-if="item.videos.length > 0">
|
<u-time-line>
|
<u-time-line-item v-for="video in item.videos" :key="video._id">
|
<template v-slot:node>
|
<view class="u-node"></view>
|
</template>
|
<template v-slot:content style="position: relative;">
|
<view @click="goVideo(video)">
|
<view>{{video.title}}</view>
|
<view>
|
直播时间:{{vk.pubfn.timeFormat(new Date(video.start_time),"yyyy-MM-dd hh:mm")}}
|
</view>
|
<view class="study_status" v-if="video.end_time<=Date.now()">
|
回看
|
</view>
|
<view class="study_status" v-if="video.start_time>Date.now()">
|
等待直播
|
</view>
|
<view class="study_status"
|
v-if="video.start_time<=Date.now()&&video.end_time>=Date.now()">
|
直播中
|
</view>
|
</view>
|
</template>
|
</u-time-line-item>
|
</u-time-line>
|
</view>
|
<view class="collapse-item" v-else>
|
暂无视频
|
</view>
|
</u-collapse-item>
|
</u-collapse>
|
</block>
|
<empty v-else :tipText="'暂未更新课程'"></empty>
|
</view>
|
</scroll-view>
|
</swiper-item>
|
<swiper-item class="swiper-item" style="box-sizing: border-box;">
|
<scroll-view :scroll-y="scrollFlag">
|
<mp-html :content="course.common_problem"></mp-html>
|
</scroll-view>
|
</swiper-item>
|
<swiper-item class="swiper-item">
|
<scroll-view :scroll-y="scrollFlag">
|
<view class="chapters">
|
<block v-if="chapterList && chapterList.length > 0">
|
<u-collapse event-type="close" :arrow="true" :accordion="false">
|
<u-collapse-item :index="index" :title="item.title" v-for="(item, index) in chapterList"
|
:key="item._id">
|
<view class="collapse-item collapse-item-word" v-if="!vk.pubfn.isNull(item.word)"
|
@click="checkPdf(item.word.url)">
|
<view class="u-node"></view>
|
{{item.word.title}}
|
</view>
|
<view class="collapse-item" v-else>
|
暂无讲义
|
</view>
|
</u-collapse-item>
|
</u-collapse>
|
</block>
|
<empty v-else :tipText="'暂未更新讲义'"></empty>
|
</view>
|
</scroll-view>
|
</swiper-item>
|
</swiper>
|
|
<view class="flex-row section_5">
|
<view class="flex-col items-center button" v-if="!isBuy" @click="buy(2)">
|
<text>报名</text>
|
</view>
|
<view class="flex-col items-center button" v-else-if="passTime" @click="buy(1)">
|
<text>重新购买</text>
|
</view>
|
<view class="flex-col items-center button" v-else @click="starWatch">
|
<text>开始学习</text>
|
</view>
|
<!-- <view class="star" @tap="changeStar">
|
<block v-if="star == 0">
|
<u-icon name="star" color="#000" size="50"></u-icon>
|
<text class="text_18">收藏</text>
|
</block>
|
<block v-else>
|
<u-icon name="star-fill" color="#000" size="50"></u-icon>
|
<text class="text_18">已收藏</text>
|
</block>
|
</view> -->
|
</view>
|
|
<u-toast ref="uToast" />
|
</view>
|
</template>
|
|
<script>
|
import util from '@/utils/util'
|
var that = this
|
var vk // vk依赖
|
export default {
|
data() {
|
return {
|
course: {
|
title: "",
|
short_description: "",
|
user_count: "",
|
charge: 0,
|
thumb: ""
|
},
|
attachs: [],
|
navTab: 'desc',
|
isCollect: false,
|
isBuy: false,
|
star: 0,
|
passTime: false,
|
videoWatchedProgress: [],
|
comments: [],
|
commentUsers: [],
|
courseId: 0,
|
commentContent: '',
|
isIos: util.isIos(),
|
list: [{
|
name: '课程介绍'
|
}, {
|
name: '课程目录'
|
}, {
|
name: '常见问题'
|
}, {
|
name: '讲义'
|
}],
|
current: 0,
|
swiperCurrent: 0,
|
// 滚动旗帜
|
scrollFlag: false,
|
// 视频总数
|
videoNum: 0,
|
// 章节视频及讲义列表
|
chapterList: []
|
};
|
},
|
filters: {
|
durationForHuman(data) {
|
return util.durationForHuman(data)
|
}
|
},
|
onLoad(options) {
|
that = this
|
vk = that.vk;
|
this.courseId = options._id
|
},
|
onShow: function() {
|
this.getCourse();
|
},
|
computed: {
|
canShowVideo() {
|
return (item) => {
|
if (!this.isBuy || item.videos.length == 0) return false
|
for (let key in item.videos) {
|
if (vk.pubfn.isNotNull(item.videos[key].watch_info)) return false
|
}
|
return true
|
}
|
}
|
},
|
methods: {
|
transVipRole(role) {
|
let all_role = vk.getVuex('$app.vipRole')
|
let show_role = all_role.filter(v => role.includes(v.value)).map(v => v.label)
|
return show_role.join('、')
|
},
|
// 时间转换
|
timeFormat(s) {
|
let day = Math.floor(s / (24 * 3600)); // Math.floor()向下取整
|
let hour = Math.floor((s - day * 24 * 3600) / 3600);
|
let minute = Math.floor((s - day * 24 * 3600 - hour * 3600) / 60);
|
let second = s - day * 24 * 3600 - hour * 3600 - minute * 60;
|
if (hour) {
|
return hour + ":" + minute + ":" + second;
|
} else {
|
if (second < 10) {
|
if (minute < 10) {
|
return "0:0" + minute + ":" + second;
|
} else {
|
return "0:" + minute + ":" + second;
|
}
|
} else {
|
return "0:" + minute + ":" + second;
|
}
|
}
|
},
|
// 视频跳转
|
goVideo(video) {
|
if (!video.free_seconds && !that.isBuy) {
|
this.$refs.uToast.show({
|
title: '购买课程后即可观看直播',
|
type: 'warning',
|
})
|
return
|
}
|
if (that.passTime) {
|
this.$refs.uToast.show({
|
title: '课程已过期,请重新购买',
|
type: 'warning',
|
})
|
return
|
}
|
if (video.end_time <= Date.now()) {
|
vk.callFunction({
|
url: 'client/liveCourse/kh/getHfRoomSign',
|
title: '请求中...',
|
data: {
|
room_id: video.room_id
|
},
|
success: function(data) {
|
vk.navigateTo('/pages/webview/webview?url=' + data.data + '&type=2');
|
}
|
});
|
} else {
|
vk.callFunction({
|
url: 'client/liveCourse/kh/getGoRoomSign',
|
title: '加载中...',
|
data: {
|
room_id: video.room_id,
|
user_number: vk.getVuex('$user.userInfo').username,
|
user_role: 2,
|
user_name: vk.getVuex('$user.userInfo').nickname,
|
user_avatar: vk.getVuex('$user.userInfo').avatar || ''
|
},
|
success(data) {
|
let {
|
room_id,
|
user_number,
|
user_name,
|
user_role,
|
user_avatar,
|
sign
|
} = data.data
|
console.log(JSON.stringify(data))
|
vk.navigateTo(
|
`/pages/webview/webview?room_id=${room_id}&user_number=${user_number}&user_name=${user_name}&user_role=${user_role}&user_avatar=${user_avatar}&sign=${sign}` +
|
'&type=3');
|
|
}
|
})
|
|
}
|
|
|
},
|
buy(pass) {
|
// 跳转确认订单页面
|
let url =
|
`/uni_modules/uce-course/pages/detail/order-confirm?course_id=${this.courseId}&pass=${pass}&type=2`
|
uni.vk.navigateTo(url)
|
},
|
// 开始学习
|
starWatch() {
|
this.swiperCurrent = 1
|
},
|
getCourse() {
|
uni.vk.callFunction({
|
url: 'client/liveCourse/pub/detail',
|
title: "加载中...",
|
data: {
|
_id: this.courseId,
|
need_user_info: true
|
},
|
success(res) {
|
// 处理详情
|
if (res.data.courses.render_desc) {
|
// 富文本图片溢出 以及衔接有空隙
|
res.data.courses.render_desc = res.data.courses.render_desc.replace(/\<img/gi,
|
'<img style="max-width:100%;height:auto;display:block;" ');
|
}
|
that.course = res.data.courses
|
that.isBuy = res.data.has_buy
|
that.star = res.data.star
|
that.chapterList = res.data.test
|
that.videoNum = 0
|
if (that.isBuy) that.passTime = res.data.endTime < new Date().getTime()
|
|
that.chapterList.map(v => {
|
that.videoNum += v.videos.length
|
})
|
}
|
});
|
},
|
// tabs通知swiper切换
|
tabsChange(index) {
|
this.swiperCurrent = index;
|
},
|
// swiper-item左右移动,通知tabs的滑块跟随移动
|
transition(e) {
|
let dx = e.detail.dx;
|
this.$refs.uTabs.setDx(dx);
|
},
|
// 由于swiper的内部机制问题,快速切换swiper不会触发dx的连续变化,需要在结束时重置状态
|
// swiper滑动结束,分别设置tabs和swiper的状态
|
animationfinish(e) {
|
let current = e.detail.current;
|
this.$refs.uTabs.setFinishCurrent(current);
|
this.swiperCurrent = current;
|
this.current = current;
|
},
|
// 修改收藏状态
|
changeStar() {
|
uni.vk.callFunction({
|
url: 'client/course/pub/change_star',
|
title: "加载中...",
|
data: {
|
course_id: this.courseId,
|
status: that.star, // 当前收藏状态
|
need_user_info: true
|
},
|
success(res) {
|
if (res.code == 0) that.star = res.noStatus
|
}
|
})
|
},
|
checkPdf(url) {
|
if (!that.isBuy) {
|
this.$refs.uToast.show({
|
title: '购买课程后即可查看',
|
type: 'warning',
|
})
|
return
|
}
|
uni.vk.navigateTo(`/uni_modules/uce-course/pages/word/word?url=${url}`)
|
}
|
},
|
// 监听整体页面滚动,tab到顶时部分可以滚动
|
onPageScroll() {
|
let query = uni.createSelectorQuery().in(this);
|
query.select('.course-tabs').boundingClientRect(data => {
|
that.scrollFlag = data.top < 20
|
}).exec();
|
}
|
}
|
</script>
|
|
<style lang="scss">
|
page {
|
background-color: #f2f2f2;
|
}
|
|
.course-thumb {
|
position: relative;
|
width: 100%;
|
height: 422rpx;
|
|
.u-image {
|
width: 100%;
|
height: 100% !important;
|
}
|
|
image {
|
width: 100%;
|
height: 100%;
|
}
|
}
|
|
.course-info {
|
position: relative;
|
width: 100%;
|
min-height: 200rpx;
|
background: #FFFFFF;
|
display: flex;
|
flex-direction: column;
|
justify-content: space-between;
|
padding: 30rpx 30rpx 20rpx 30rpx;
|
border-radius: 30rpx 30rpx 0px 0px;
|
margin-top: -30rpx;
|
|
.course-title {
|
font-size: 32rpx;
|
font-weight: 800;
|
color: #000000;
|
}
|
|
.group_2 {
|
margin-top: 62rpx;
|
|
.text_4 {
|
margin: 8rpx 0 10rpx;
|
color: rgb(153, 153, 153);
|
font-size: 24rpx;
|
line-height: 29rpx;
|
white-space: nowrap;
|
}
|
|
.text_2 {
|
color: rgb(255, 0, 0);
|
font-size: 38rpx;
|
line-height: 46rpx;
|
white-space: nowrap;
|
font-weight: bold;
|
}
|
|
.text_3 {
|
margin: 10rpx 10rpx 0;
|
color: rgb(153, 153, 153);
|
font-size: 24rpx;
|
line-height: 29rpx;
|
text-decoration: line-through;
|
}
|
}
|
}
|
|
.course-tabs {
|
margin-top: 10rpx;
|
position: sticky;
|
top: 0;
|
background: #FFFFFF;
|
z-index: 999;
|
}
|
|
|
.swiper-item-box {
|
position: relative;
|
min-height: 100vh;
|
padding-bottom: 104rpx;
|
|
.swiper-item {
|
border-top: 1px solid #efefef;
|
background: #FFFFFF;
|
position: relative;
|
|
scroll-view {
|
height: 100% !important;
|
}
|
}
|
}
|
|
.course-like {
|
position: absolute;
|
bottom: 10rpx;
|
right: 40rpx;
|
}
|
|
.chapters {
|
padding: 20rpx 30rpx;
|
|
.collapse-item {
|
padding: 10rpx 40rpx 0;
|
|
.u-node {
|
width: 20rpx;
|
height: 20rpx;
|
background: #FFFFFF;
|
border: 2rpx solid #FDD303;
|
border-radius: 50%;
|
}
|
|
.study_status {
|
width: 120rpx;
|
margin-top: 20rpx;
|
border: 2rpx solid #333333;
|
border-radius: 26rpx;
|
position: absolute;
|
text-align: center;
|
font-size: 24rpx;
|
font-weight: bold;
|
line-height: 38rpx;
|
color: #333333;
|
top: 28rpx;
|
right: 0;
|
}
|
}
|
|
.collapse-item-word {
|
padding: 30rpx 40rpx;
|
display: flex;
|
align-items: center;
|
|
.u-node {
|
margin-right: 10rpx;
|
}
|
}
|
}
|
|
.section_5 {
|
position: fixed;
|
bottom: 0;
|
width: 100%;
|
padding: 22rpx 20rpx;
|
background-color: rgb(255, 255, 255);
|
box-shadow: 0px -6rpx 16rpx 0px rgba(0, 0, 0, 0.08);
|
|
.button {
|
padding: 14rpx 0 12rpx;
|
flex: 1 1 auto;
|
color: rgb(255, 255, 255);
|
font-size: 32rpx;
|
line-height: 36rpx;
|
white-space: nowrap;
|
background-color: rgb(51, 51, 51);
|
border-radius: 32rpx;
|
height: 64rpx;
|
}
|
|
.star {
|
display: flex;
|
align-items: center;
|
margin-left: 34rpx;
|
}
|
|
.text_18 {
|
width: 84rpx;
|
margin-left: 10rpx;
|
align-self: center;
|
color: rgb(51, 51, 51);
|
font-size: 28rpx;
|
line-height: 34rpx;
|
white-space: nowrap;
|
}
|
}
|
|
/deep/ .study_status_all .u-collapse-head {
|
position: relative;
|
}
|
|
/deep/ .study_status_all .u-collapse-head::after {
|
// content: '未学习';
|
position: absolute;
|
top: 18rpx;
|
right: 90rpx;
|
width: 120rpx;
|
border: 2rpx solid #333333;
|
border-radius: 26rpx;
|
position: absolute;
|
text-align: center;
|
font-size: 24rpx;
|
font-weight: bold;
|
line-height: 38rpx;
|
}
|
|
/deep/ .u-time-axis-item {
|
width: auto !important;
|
padding: 10rpx 0 !important;
|
}
|
|
|
.vip-tip {
|
position: relative;
|
width: 100%;
|
padding-top: 40rpx;
|
color: #666c80;
|
font-size: 24rpx;
|
|
&:before {
|
left: 0;
|
top: 20rpx;
|
width: 100%;
|
height: 2rpx;
|
content: "";
|
position: absolute;
|
-webkit-transform: scaleY(.5);
|
transform: scaleY(.5);
|
-webkit-transform-origin: top center;
|
transform-origin: top center;
|
background-color: #edeff2;
|
}
|
}
|
</style>
|