src\router\index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Vuex from 'vuex'
import Index from '../components/Index.vue'
import Course from '../components/Course.vue'
Vue.use(VueRouter)
Vue.use(Vuex)
const videoDetail = () => import('../components/videoDetail.vue');
const routes = [
{
path: '/',
name: 'Index',
component: Index,
meta: {
title: '首页'
}
},
{
path: '/Course',
name: 'Course',
component: Course,
meta: {
title: '课程简介页'
}
},
{
path: '/videoDetail',
name: 'videoDetail',
component: videoDetail,
meta: {
title: '视频播放页'
}
}
]
const router = new VueRouter({
routes
})
export default router
src\components\Index.vue
<script>
import Header from "./Header/Header"; //顶部登录条
import Footer from "./Footer/index"; //顶部登录条
export default {
name: "Index",
components: {
Header,
Footer,
},
data() {
return {
activeName: "allLesson",
courseList: [], // 课程集合
myCourseList: [], // 我购买过的课程列表
isLogin: false, //登录状态
user: null, // 已登录的用户对象信息
};
},
created() {
this.user = JSON.parse(localStorage.getItem("user"));
if (this.user != null) {
this.isLogin = true; //已登录
this.getMyCourseList(); // 调用查询我购买的课程方法
}
this.getCourseList(); //当组件创建完毕,就调用获取所有课程的方法
},
methods: {
changeCourseTab(tabName) {
this.classSelect = tabName;
sessionStorage && sessionStorage.setItem("courseTab", tabName);
},
gotoDetail(item) {
this.$router.push({ name: "Course", params: { course: item } });
},
getCourseList() {
// 去dubbo服务获取全部课程的数据
return this.axios
.get("http://localhost:80/course/getAllCourse")
.then((result) => {
console.log(result);
this.courseList = result.data;
})
.catch((error) => {
this.$message.error("获取课程信息失败!");
});
},
getMyCourseList() {
return this.axios
.get(
"http://localhost:80/course/getCourseByUserId/" + this.user.content.id
)
.then((result) => {
console.log(result);
this.myCourseList = result.data;
})
.catch((error) => {
this.$message.error("获取课程信息失败!");
});
},
},
};
</script>
<!-- 课程信息展示开始 -->
<li
class="course-li"
v-for="(item, index) in courseList"
:key="index"
>
<!-- 课程封面图 -->
<img
:src="item.courseImgUrl"
class="teacher-portrait hover-pointer"
/>
<!-- 课程文字信息 -->
<div class="content-main">
<!-- 课程标题 -->
<div class="content-title hover-pointer">
<div
class="p-title"
style="text-align: left"
@click="gotoDetail(item)"
>
<span>
{{ item.courseName }}
</span>
</div>
<!-- 作者和职称 -->
<p class="p-title-buy text-overflow">
<span class="p-author-span">
{{ item.teacher.teacherName }}
</span>
<span class="p-author-line" />
<span class="p-author-span">
{{ item.teacher.position }}
</span>
</p>
<p></p>
<!-- 课程简单描述 -->
<p class="p-describe" style="text-align: left">
{{ item.brief }}
</p>
</div>
<!-- 课程前两个章节信息 -->
<ul class="content-course" style="text-align: left">
<!-- 章节1 : 免费试看,通常是第一章的前两节课 -->
<li
class="content-course-lesson text-overflow"
style="width: 300px"
v-for="(lesson,
index) in item.courseSections[0].courseLessons.slice(0, 2)"
:key="index"
>
<!-- 免费试看图标 -->
<img
src="@/assets/course-list/free-course.png"
class="free-label hover-pointer"
/>
<span class="theme-span hover-pointer">
{{ lesson.theme }}
</span>
</li>
</ul>
<!-- 价格信息 -->
<div class="content-price" style="text-align: left">
<p class="content-price-p">
<span class="content-price-orange-sm">¥</span>
<span class="content-price-orange">{{
item.discounts
}}</span>
<span class="current-price">
<span class="current-price-unite">¥</span>
{{ item.price }}
</span>
<span class="activity-name">成就自己</span>
<span class="content-price-buy"
>{{ item.sales }}人购买</span
>
</p>
<div class="btn btn-green btn-offset">立即购买</div>
</div>
</div>
</li>
<!-- 课程信息结束 -->
src\components\Header\Header.vue
<script>
// import wxlogin from 'vue-wxlogin'; // 引入
export default {
name: "Header",
components: {
// wxlogin // 声明引用的组件
},
props: {},
data() {
return {
isLogin: false, // 登录状态,true:已登录,false:未登录
userDTO: null, // 用来保存登录的用户信息
isHasNewMessage: false, // 是否有新的推送消息
dialogFormVisible: false, // 是否显示登录框,true:显示,false:隐藏
phone: "", // 双向绑定表单 手机号
password: "", // 双向绑定表单 密码
// appid:"wxd99431bbff8305a0", // 应用唯一标识,在微信开放平台提交应用审核通过后获得
// scope:"snsapi_login", // 应用授权作用域,网页应用目前仅填写snsapi_login即可
// redirect_uri:"http://www.pinzhi365.com/user/wxlogin", //重定向地址,(回调地址)
x: null,
};
},
computed: {},
watch: {},
mounted() {},
created() {
// 当刷新页面,组件创建成功之后,立刻检测本地储存中是否存在用户对象
this.userDTO = JSON.parse(localStorage.getItem("user"));
if (this.userDTO != null) {
this.isLogin = true; // 已登录
} else {
// 去检测微信是否登录过
this.axios
.get("http://localhost:80/user/checkWxStatus")
.then((result) => {
this.userDTO = result.data;
this.phone = this.userDTO.content.phone;
this.password = this.userDTO.content.password;
this.login(); // 走普通登录
})
.catch((error) => {
//this.$message.error("登录失败!");
});
}
!(function (a, b, c) {
function d(a) {
var c = "default";
a.self_redirect === !0
? (c = "true")
: a.self_redirect === !1 && (c = "false");
var d = b.createElement("iframe"),
e =
"https://open.weixin.qq.com/connect/qrconnect?appid=" +
a.appid +
"&scope=" +
a.scope +
"&redirect_uri=" +
a.redirect_uri +
"&state=" +
a.state +
"&login_type=jssdk&self_redirect=" +
c +
"&styletype=" +
(a.styletype || "") +
"&sizetype=" +
(a.sizetype || "") +
"&bgcolor=" +
(a.bgcolor || "") +
"&rst=" +
(a.rst || "");
(e += a.style ? "&style=" + a.style : ""),
(e += a.href ? "&href=" + a.href : ""),
(d.src = e),
(d.frameBorder = "0"),
(d.allowTransparency = "true"),
(d.sandbox = "allow-scripts allow-top-navigation allow-same-origin"), // 允许多种请求
(d.scrolling = "no"),
(d.width = "300px"),
(d.height = "400px");
var f = b.getElementById(a.id);
(f.innerHTML = ""), f.appendChild(d);
}
a.WxLogin = d;
})(window, document);
},
methods: {
goToSetting() {
this.$router.push("/setting"); // 跳转个人设置页面
},
goToLogin() {
this.dialogFormVisible = true; // 显示登录框
},
login() {
// 前去登录
return this.axios
.get("http://localhost:80/user/login", {
params: {
phone: this.phone,
password: this.password,
nickname: "",
headimg: "",
},
})
.then((result) => {
console.log(result);
this.dialogFormVisible = false; //关闭登录框
this.userDTO = result.data; // 保存返回数据中的用户对象信息
this.isLogin = true; // 更新登录状态
localStorage.setItem("user", JSON.stringify(this.userDTO)); // 将登录成功的对象信息保存到本地储存中
})
.catch((error) => {
this.$message.error("登录失败!");
});
},
// 微信登录
goToLoginWX() {
// 普通的登录表单隐藏
document.getElementById("loginForm").style.display = "none";
// 显示二维码的容器
document.getElementById("wxLoginForm").style.display = "block";
// 生成二维码
// 待dom更新之后再用二维码渲染其内容
this.$nextTick(function () {
this.createCode(); // 直接调用会报错:TypeError: Cannot read property 'appendChild' of null
});
},
// 生成二维码
createCode() {
var obj = new WxLogin({
id: "wxLoginForm", // 挂载点,二维码的容器
appid: "wxd99431bbff8305a0", // 应用唯一标识,在微信开放平台提交应用审核通过后获得
scope: "snsapi_login", // 应用授权作用域,网页应用目前仅填写snsapi_login即可
redirect_uri: "http://www.pinzhi365.com/user/wxlogin", //重定向地址,(回调地址)
href:
"data:text/css;base64,LmltcG93ZXJCb3ggLnFyY29kZSB7d2lkdGg6IDIwMHB4O30NCi5pbXBvd2VyQm94IC50aXRsZSB7ZGlzcGxheTogbm9uZTt9DQouaW1wb3dlckJveCAuaW5mbyB7d2lkdGg6IDIwMHB4O30NCi5zdGF0dXNfaWNvbiB7ZGlzcGxheTogbm9uZX1jcw0KLmltcG93ZXJCb3ggLnN0YXR1cyB7dGV4dC1hbGlnbjogY2VudGVyO30=", // 加载修饰二维码的css样式
});
},
toToIndex() {
this.$router.push("/"); //回到首页
},
toToNotic() {},
//登出
logout() {
localStorage.setItem("user", null); // 将登录成功的对象信息保存到本地储存中
this.isLogin = false; // 更新登录状态
// alert("谢谢使用,再见");
// 去检测微信是否登录过
this.axios
.get("http://localhost:80/user/logout")
.then((result) => {})
.catch((error) => {
//this.$message.error("登录失败!");
});
},
},
};
</script>
src\components\Course.vue
<!-- 课程详情 -->
<div class="container">
<div style="height: 100%">
<div class="weui-tab content-wrapper">
<div
id="vux_view_box_body"
class="weui-tab__panel vux-fix-safari-overflow-scrolling"
>
<div style="position: relative">
<div class="intro">
<div class="intro-content">
<img
class="course-img"
:src="course.courseImgUrl"
alt="课程图片"
/>
<div class="conent-wrap">
<div class="name" style="text-align: left">
{{ course.courseName }}
</div>
<div class="des text-omit" style="text-align: left">
{{ course.brief }}
</div>
<div class="title">
<div class="teacher-name text-omit">
讲师:{{ course.teacher.teacherName }}
<span class="line"></span>
{{ course.teacher.position }}
</div>
</div>
<div class="lesson-info">
<div class="boook-icon backgroun-img-set"></div>
<div class="time">
{{ totalLessons }} 讲 /
{{ course.totalDuration }} 课时
</div>
<div class="person-icon backgroun-img-set"></div>
<div class="person">{{ course.sales }}人已购买</div>
</div>
</div>
<div class="content-right">
<div class="button-wrap" @click="watchCourse(1)">
免费试看
<div class="small-arrows"></div>
</div>
</div>
</div>
</div>
</div>
<div class="public-class-container is-pc">
<el-tabs v-model="activeName">
<el-tab-pane label="课程信息" name="intro">
<div
v-html="course.courseDescription"
class="content-p pc-background"
></div>
<!-- 留言板 开始-->
<div class="message">
<div class="message-topic">
<div class="message-topic-title normal-font">
精选留言
</div>
</div>
<div>
<div class="message-edit">
<textarea
rows="20"
style="border: none; resize: none"
contenteditable="true"
placeholder="分享学习心得、思考感悟或者给自己一个小鼓励吧!"
class="edit-div pcStyle"
v-model="comment"
></textarea>
</div>
<div class="message-edit-footer flex">
<button
class="message-edit-btn disableBg"
@click="saveComment"
>
发表留言
</button>
</div>
</div>
<!-- 留言 开始 -->
<div
class="message-list"
v-for="(comment, index) in commentList"
:key="index"
>
<div class="message-list-title">
<div class="message-list-title-left">
<div class="message-list-title-left-name">
{{ comment.userName }}
</div>
<div class="message-list-title-left-tag"></div>
</div>
<!-- 已赞 data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADgAAAA4BAMAAABaqCYtAAAAJFBMVEVHcEwAuI4AtIsAtIsAtIoAtYwAtIsAtYwAtowAx5kAtIsAs4qd4c1kAAAAC3RSTlMAGMfz3VGnbTYIhXtDq8EAAAETSURBVDjLldWhb8JAFAbwg8CGhGSGzNQtULNkWUioWbJkpmYKAQaBITPLLKZysmLz+xfolUL6/XM72msh9N2X8ImaX17vrq+vVeqU39XTuK/kdEMA01jGDY4ZyYWFIRPxp0S8u+8KeBJ+WDxIGFrMJbQm7qhVYSJgr8JUwNsKtYDtCiHgPavcsDVDstsuyDk7NeYDk6G8pM3bWXNawQUijWq8QyPPpQy+50ET9bF09go5pus3cMV0feFEc2DfieZRBU7Up7fjSkwZZgz3DA8MHxl6DP8YRgxjgokimDHcMdwyfGG4ZPjJMCKoY4KJIpgz3DHcMvQYFuPpk/005t1mffHlOs/ETvxXAA0Ul3oQHsp/xD93wxfHcC4VkwAAAABJRU5ErkJggg== -->
<div
@click="cancelzan(comment)"
v-if="
JSON.stringify(comment.favoriteRecords).indexOf(
user.content.id
) >= 0
"
class="message-list-title-right"
>
<img
class="message-list-title-right-icon"
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADgAAAA4BAMAAABaqCYtAAAAJFBMVEVHcEwAuI4AtIsAtIsAtIoAtYwAtIsAtYwAtowAx5kAtIsAs4qd4c1kAAAAC3RSTlMAGMfz3VGnbTYIhXtDq8EAAAETSURBVDjLldWhb8JAFAbwg8CGhGSGzNQtULNkWUioWbJkpmYKAQaBITPLLKZysmLz+xfolUL6/XM72msh9N2X8ImaX17vrq+vVeqU39XTuK/kdEMA01jGDY4ZyYWFIRPxp0S8u+8KeBJ+WDxIGFrMJbQm7qhVYSJgr8JUwNsKtYDtCiHgPavcsDVDstsuyDk7NeYDk6G8pM3bWXNawQUijWq8QyPPpQy+50ET9bF09go5pus3cMV0feFEc2DfieZRBU7Up7fjSkwZZgz3DA8MHxl6DP8YRgxjgokimDHcMdwyfGG4ZPjJMCKoY4KJIpgz3DHcMvQYFuPpk/005t1mffHlOs/ETvxXAA0Ul3oQHsp/xD93wxfHcC4VkwAAAABJRU5ErkJggg=="
alt=""
/>
<div class="message-list-title-right-praise">
{{ comment.likeCount }}
</div>
</div>
<!-- 没点过赞 -->
<div
@click="zan(comment)"
v-else
class="message-list-title-right"
>
<img
class="message-list-title-right-icon"
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADgAAAA4BAMAAABaqCYtAAAAKlBMVEVHcExnZ2dzc3NmZmZqampmZmZmZmZnZ2dnZ2dnZ2dmZmZoaGhmZmZmZmZl+8SAAAAADXRSTlMA/AbsFtilbj5YwSqJPyESoQAAAZxJREFUOMt1lTtLA1EQha8xRhPTBEmhuKCCoNgoIlYLMcRKBG0sxIUgCDaBSDohEO0FEbQyIBZaBazERvAPWCwxPnP+i3tnrlGTmVPswn73NXNm7hrzq9m9kZ2ckTUUABifkOEBrK7liR7BMRFOA/uFc+BUgnV8mFisEW5IsIFi9FzBuwR91KJnAm8S9EIbxSBeBRZHk86MrBQJWjymJUC3nlugSyk+SQyhANfxos+s4krfM0DZvmbw2cuSCHNGi3PAfUygXYiU79ryyw1ibf0xZ9intBsz6SBadx24iiZXz8kPxCiTtYdLPzKTVFkkLQAZO/VikwYW/x/wHohcT/MiPQE8W9frxJrlbpiw4xvA0vbNmWyhj2Nrhmy+B7nEyTsN0rIaJAc0SDWqwX7rhAYfMa/Dui0bDZbwZAwUGNjWUWActnUUyN2hwDTaOkxRaSiwj6pRhjHKgTazSkWlwBK1jgIpBwrkHCgwyZ0oQ86BAjkHCjziG0KE8YBvCA/5KacOm6sgrHFAotouT6J23bkkLbsNDjM9yt7yP+IbQYga5De+eBMAAAAASUVORK5CYII="
alt=""
/>
<div class="message-list-title-right-praise">
{{ comment.likeCount }}
</div>
</div>
</div>
<div class="message-list-content">
{{ comment.comment }}
</div>
<!--删除留言(必须登录才能删除自己的)-->
<!--
<div class="message-delete pointer">
<img class="message-delete-icon" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADgAAAA4BAMAAABaqCYtAAAAD1BMVEWZmZn4+fqysrPu7/DS09OEJUPlAAAAf0lEQVQ4y+3VwQ2AIAwF0C9hAAUHgDgBToD7L2UiUMDiwQMXpQfS9B3ohQ+WVDtibTRCarRJKBzDGVQTQ59RMjSwoVEQDIF4lQYa2Oi6IR6qJ5Yr1Et9ExvnwIGv8A9vxdWmCzRFdMdIF4Se54wkVBwtYQ7/+hMIe643Fcc1PgEbl0u1B0v+VgAAAABJRU5ErkJggg==" alt="">删除
</div>
-->
</div>
<!-- 留言 结束 -->
</div>
<!-- 留言板 结束-->
</el-tab-pane>
<el-tab-pane label="目录" name="directory">
<div
class="class-menu-contaniner list-page-container more-sections more-sections-padding"
>
<!-- 第一章 开始 -->
<div v-for="section in course.courseSections.slice(0, 1)">
<div class="section-name single-line">
{{ section.sectionName }}
</div>
<div class="class-menu-block">
<!-- 每节课 开始 -->
<div
class="class-level-one over-ellipsis"
@click="
watchCourse(
1,
lesson.id,
index,
lesson.courseMedia
)
"
v-for="(lesson, index) in section.courseLessons"
:key="index"
>
<div class="text-wrap">
<div class="content">{{ lesson.theme }}</div>
<div
class="item-status-wrap item-status-wrap-list"
>
<!-- 第一章,前两节 -->
<div v-if="index < 2">
<!-- 未登录 => 试看 -->
<div
v-if="!isLogin"
class="item-status test-watch"
>
试看
</div>
<!-- 已登录,未购买 => 试看 -->
<div
v-else-if="isLogin && !isBuy"
class="item-status test-watch"
>
试看
</div>
<!-- 已登录,已购买 => 播放 -->
<div v-else class="item-status test-watch">
播放
</div>
</div>
<!-- 第一章,除了前两节的 -->
<div v-if="index > 1">
<!-- 未登录 => 锁 -->
<div
v-if="!isLogin"
class="item-status lock"
></div>
<!-- 已登录,未购买 => 锁 -->
<div
v-else-if="isLogin && !isBuy"
class="item-status lock"
></div>
<!-- 已登录,已购买 => 播放 -->
<div v-else class="item-status test-watch">
播放
</div>
</div>
</div>
</div>
</div>
<!-- 每节课 结束 -->
</div>
</div>
<!-- 第一章 结束 -->
<!-- 其余章 开始 -->
<div
v-for="section in course.courseSections.slice(
1,
course.courseSections.length
)"
>
<div class="section-name single-line">
{{ section.sectionName }}
</div>
<div class="class-menu-block">
<!-- 每节课 开始 -->
<div
class="class-level-one over-ellipsis"
@click="
watchCourse(
2,
lesson.id,
index,
lesson.courseMedia
)
"
v-for="(lesson, index) in section.courseLessons"
:key="index"
>
<div class="text-wrap">
<div class="content">{{ lesson.theme }}</div>
<div
class="item-status-wrap item-status-wrap-list"
>
<!-- 未登录 => 锁 -->
<div
v-if="!isLogin"
class="item-status lock"
></div>
<!-- 已登录,未购买 => 锁 -->
<div
v-else-if="isLogin && !isBuy"
class="item-status lock"
></div>
<!-- 已登录,已购买 => 播放 -->
<div v-else class="item-status test-watch">
播放
</div>
</div>
</div>
</div>
<!-- 每节课 结束 -->
</div>
</div>
<!-- 其余章 结束 -->
</div>
</el-tab-pane>
</el-tabs>
<div class="tab-fix-wrap"></div>
<div></div>
</div>
</div>
</div>
</div>
<!-- 微信支付二维码-->
<el-dialog
:visible.sync="dialogFormVisible"
style="width: 800px; margin: 0px auto"
>
<h1 style="font-size: 30px; color: #00b38a">微信扫一扫支付</h1>
<div id="qrcode" style="width: 210px; margin: 20px auto"></div>
<h2 id="statusText"></h2>
<p id="closeText"></p>
</el-dialog>
<!-- 底部购买 -->
<div
class="public-class-footer"
slot="bottom"
style="border: 1px solid #eee; height: 60px; text-align: left"
>
<span class="product-descript" style="font-size: 0.347rem"
>成就自己</span
>
<span class="current-price" style="font-size: 28px">
<span class="current-price-unite" style="font-size: 0.347rem">
¥</span
>{{ course.discounts }}
</span>
<span class="current-price price">
<span class="current-price-unite">¥</span>
{{ course.price }}
</span>
<button
@click="buy(7)"
type="button"
class="weui-btn purchase-button weui-btn_mini weui-btn_primary"
style="width: 155px; height: 45px; font-size: 17px"
>
立即购买
<!-- ::after -->
</button>
</div>
</div>
<script>
import Header from "./Header/Header"; //顶部登录条
import Footer from "./Footer/index"; //顶部登录条
import QRCode from "qrcodejs2"; // 引入qrcodejs
export default {
name: "Course",
components: {
Header,
Footer,
QRCode, // 声明组件
},
data() {
return {
activeName: "intro",
course: null,
totalLessons: 0, // 本门课程的总节数
commentList: null, // 所有留言
isLogin: false, // false 未登录
isBuy: false, // false 未购买
user: null, // 当前用户
myCourseList: [], // 当前用户购买过的所有课程
comment: null, // 待发表的留言内容
dialogFormVisible: false, //默认false:隐藏,true:显示
time: null, // 计时对象
orderNo: "", // 订单编号
};
},
created() {
this.course = this.$route.params.course; // 从路由中获得参数对象赋值给本组件的参数
// 检测是否登陆
this.user = JSON.parse(localStorage.getItem("user"));
if (this.user != null) {
this.isLogin = true; // 已登录
this.getMyCourseList(); // 查询登录用户购买的所有课程
}
// 计算多少节课要讲
let x = 0;
for (let i = 0; i < this.course.courseSections.length; i++) {
let section = this.course.courseSections[i]; //每一章
for (let j = 0; j < section.courseLessons.length; j++) {
x++;
}
}
this.totalLessons = x;
// 获得所有留言
this.getComment();
},
methods: {
//播放视频 ( 章节,小节课编号,每节课的索引,每节课的视频对象)
watchCourse(status, lessonid, index, media) {
if (media == null || media == "") {
this.$message.error("播放失败,暂无视频!");
} else {
// 试看的可以跳转播放页面
if (status == 1 && index < 2) {
this.$message.success("观看第【" + lessonid + "】节课程视频!");
this.$router.push({
name: "videoDetail",
params: {
course: this.course,
lessonid: lessonid,
isBuy: this.isBuy,
},
});
} else {
// 锁上的,先验证是否登录
if (!this.isLogin) {
this.$message.success("请先登录!");
} else {
// 登录后,再验证是否购买过
if (!this.isBuy) {
this.$message.warning("请购买并解锁,才能观看本视频!");
} else {
this.$message.success("观看第【" + lessonid + "】节课程视频!");
this.$router.push({
name: "videoDetail",
params: {
course: this.course,
lessonid: lessonid,
isBuy: this.isBuy,
},
});
}
}
}
}
},
// 购买课程
buy(courseid) {
//alert("购买第【" + courseid + "】门课程成功,加油!");
this.dialogFormVisible = true; //显示提示框
// 待dom更新之后再用二维码渲染其内容
this.$nextTick(function () {
this.createCode(); // 直接调用会报错:TypeError: Cannot read property 'appendChild' of null
});
},
// 生成二维码
createCode() {
// 去获取支付连接
this.axios
.get("http://localhost:80/order/createCode", {
params: {
courseid: this.course.id,
coursename: this.course.courseName,
price: 1, //测试支付金额固定为1分钱,真实上线环境再改回此真实价钱:this.course.discounts
},
})
.then((result) => {
console.log(result);
// QRCode(存放二维码的dom元素id,二维码的属性参数)
let qrcode = new QRCode("qrcode", {
width: 200,
height: 200,
text: result.data.code_url, // 将返回的数据嵌入到二维码中
});
this.orderNo = result.data.orderId;
// 保存订单, 状态为:已创建 0
this.saveOrder();
// 检查支付状态
this.axios
.get("http://localhost:80/order/checkOrderStatus", {
params: {
orderId: result.data.orderId, // 传递 订单编号 进行查询
},
})
.then((result) => {
if (result.data.trade_state == "SUCCESS") {
document.getElementById("statusText").innerHTML =
"<i style='color:#00B38A' class='el-icon-success'></i> 支付成功!";
// 支付成功
this.updateOrder(20);
}
/*
else if(result.data.trade_state=="NOTPAY"){
document.getElementById("statusText").innerHTML = "<i style='color:#00B38A' class='el-icon-success'></i> 未支付!";
this.updateOrder(10);
}
*/
// 3秒后关闭二维码窗口
let s = 3;
this.closeQRForm(s);
})
.catch((error) => {
this.$message.error("查询订单失败!");
});
})
.catch((error) => {
this.$message.error("生成二维码失败!");
});
},
// 倒计时关闭二维码窗口
closeQRForm(s) {
let that = this;
that.time = setInterval(function () {
document.getElementById("closeText").innerHTML =
"( " + s-- + " ) 秒后关闭本窗口";
if (s == 0) {
clearInterval(that.time); // 停止计时器
that.dialogFormVisible = false; // 二维码窗口隐藏
that.isBuy = true; // 修改购买状态(已购买)
}
}, 1000);
},
// 保存订单
saveOrder() {
return this.axios
.get("http://localhost:80/order/saveOrder", {
params: {
orderNo: this.orderNo,
user_id: this.user.content.id,
course_id: this.course.id,
activity_course_id: this.course.id,
source_type: 1,
},
})
.then((result) => {
// console.log(result);
console.log("保存订单");
})
.catch((error) => {
this.$message.error("保存订单失败!");
});
},
// 更新订单的状态
updateOrder(statusCode) {
return this.axios
.get("http://localhost:80/order/updateOrder", {
params: {
orderNo: this.orderNo,
status: statusCode,
},
})
.then((result) => {
console.log("更新订单【" + this.orderNo + "】状态:" + statusCode);
})
.catch((error) => {
this.$message.error("更新订单失败!");
});
},
// 获取本课程的全部留言
getComment() {
return this.axios
.get(
"http://localhost:80/course/comment/getCourseCommentList/" +
this.course.id +
"/1/20"
)
.then((result) => {
this.commentList = result.data;
console.log("获取留言:");
console.log(this.commentList);
})
.catch((error) => {
this.$message.error("获取留言信息失败!");
});
},
// 发表留言
saveComment() {
return this.axios
.get("http://localhost:80/course/comment/saveCourseComment", {
params: {
courseid: this.course.id,
userid: this.user.content.id,
username: this.user.content.name,
comment: this.comment,
},
})
.then((result) => {
// console.log(result);
// 重新获取本门课的全部留言信息
this.getComment();
})
.catch((error) => {
this.$message.error("发表留言失败!");
});
},
// 查询当前用户购买过的全部课程
getMyCourseList() {
return this.axios
.get(
"http://localhost:80/course/getCourseByUserId/" + this.user.content.id
)
.then((result) => {
console.log(result);
this.myCourseList = result.data;
// 检测当前的课程是否购买过
for (let i = 0; i < this.myCourseList.length; i++) {
if (this.myCourseList[i].id == this.course.id) {
this.isBuy = true; // 标记购买过本课程
break;
}
}
})
.catch((error) => {
this.$message.error("获取课程信息失败!");
});
},
// 点赞
zan(comment) {
return this.axios
.get(
"http://localhost:80/course/comment/saveFavorite/" +
comment.id +
"/" +
this.user.content.id
)
.then((result) => {
// console.log(result);
// 重新获取本门课的全部留言信息
this.getComment();
})
.catch((error) => {
this.$message.error("点赞失败!");
});
},
// 取消赞
cancelzan(comment) {
return this.axios
.get(
"http://localhost:80/course/comment/cancelFavorite/" +
comment.id +
"/" +
this.user.content.id
)
.then((result) => {
// console.log(result);
// 重新获取本门课的全部留言信息
this.getComment();
})
.catch((error) => {
this.$message.error("取消赞失败!");
});
},
},
};
</script>
src\components\videoDetail.vue
<div id="videoDetail">
<div class="detail-container">
<div class="left-container top-container">
<nav class="nav">
<div class="nav-back" @click="goBack">
<span class="kw-icon-back"> < </span>
<span style=""> 返回</span>
</div>
<span style="position:absolute;left:80px;">
{{course.courseName}} > {{lessonName}}</span
>
</nav>
<div class="video-content calc">
<div class="video-container" >
<div
id="player-video-vontainer"
class="player-container video-container"
>
<div
style="min-width:750px;min-height:550px; max-height:940px"
class="video"
>
<video
style="width: 100%; height: 100%;max-height:920px"
id="myvideo"
src=""
@canplay="getInit"
@timeupdate="handlerNowTime"
@click="play"
/>
<div class="controls">
<div class="con_left">
<!-- 播放 -->
<i
:class="{
'el-icon-video-play': !isplay,
'el-icon-video-pause': isplay,
}"
@click="play"
style="font-size:40px"
></i>
<span>{{ nowTime }}/{{ totalTime }}</span>
</div>
<div class="con_right">
<!-- 音量 -->
<i
class="el-icon-headset"
@click="play"
style="font-size:40px"
></i>
<!-- 全屏 -->
<i
class="el-icon-monitor"
@click="play"
style="font-size:40px"
></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="right-container bottom-container">
<div style="height: 100%;">
<div class="detail-part-content-title">课程目录</div>
<div class="study-percent-tip">
<div class="week-progress">
<img
class="video-book"
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAADHUlEQVRoQ+2a30sUURTHv3dMS60Xg8AIQV+ChCBmJqInqXAx6iXah6CghzCkiMz8C3qJfllRhNJDEEWwEUFFJBW9KMbMEAkWvbjgg0FRYO76o92dE1Ma686d8c4y7rrDncfdc+85n3t+zL1zD0PEHxZxPkjASvewsAd1XW8lohNE1A6gCcD6EsOnAEwwxgYZY3cNwxgT0b8sYDwer0kmk9eIqAuAIjJpCWRsxtid5ubmc4lE4refPl9AB258fPwlgD0lMLoYFW9bWlo6/CB9ATVNu0VEp4rRXKoxjLHbpmme9tLnCejknG3bo6soLL0YbEVRtnvlpCegpml9RHSWM2sGwCvG2KSIl4ioU0SuUIYxNpD/GxFtBhADUM2RvW6aZjdPjyegqqpOldpWMCijKEqbYRjDokarqkqisvlylmW5bNN1fbdt2+84kJ8sy2oNCjjNeRU8tyzrYBCDwwR09Kqq+gzAgQIbUpZlbQgK6Fp5J2xM0zxZTkBN0/p5Yc/zuGOnX4hKQBFPhh2i0oMFqx5qiNJIx5acbV8CoY1AjY6uXWd+iDjaJTNycyN33IUHqZkX7+frCv9c8RxcgPtIRA35ysMGvPgojafDcy74FQfMDsceEtGRQs3RARyKTS6GpYgH69b9y46ZOf4+wCtEy+bBzFA711KeB/fuqEH3ofq/gH1P0njzwX3iqUjApk1V6I3XQ9+6dDtpfMngciKNiW+5/86vKMC11QzH22txbF8t1lTxi2o2B9x/PYt7g7OYzxAqBvD8wDR6DtejsUHsY8DXnzauPk7jSid3a4lVl4NFvQR9BknAldrJeFVR6cGAKyBDVIbowgrwznF+J3qZgwFzzUtc5qDMQZmD/M+GssjIIiO2ArKKyioqq6isomLVokgpWWQCFJlAF6CletH39P/C0Jhzi77kKeoCNNAVdikAR5NZdN2YQs52xXfwK+ygTQj7d9Ycra5irlufIlPNNez7VA4jnzM8ODDGgjchRL6NxFnCSDcCOYCRb+VahIxsM15+pke2nTKsKliueZbtFy2XYWHplYBhrWS55vkDgsoDZgBZavwAAAAASUVORK5CYII="
alt=""
/>
<span class="progress-label">--</span>
</div>
</div>
<div class="detail-part-content-pc calc detail-part-content">
<div class="content-fold">
<div class="content-fold-img"></div>
</div>
<div class="content-container">
<!-- 第一章 开始 -->
<div v-for="section in course.courseSections.slice(0,1)">
<div class="content-label">
<div class="content-label-title single-line">{{section.sectionName}}</div>
<img
class="arrow-icon"
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkBAMAAAATLoWrAAAAGFBMVEVHcEz///////////////////////////8dS1W+AAAAB3RSTlMAgwWyMeGgBsFrrQAAAFVJREFUKM9jYBiugMUBQ0i8EF2EsbxcAF1ReXkhuqJiczRl4uVGyqjKgIoUmFCVARUxMKAoAyliYEBRBlaEqiwcpAikrBShKglCqyFUMcEYCgwjBAAAeaoQrHtg6QoAAAAASUVORK5CYII="
alt=""
/>
</div>
<!-- 第一章 开始 -->
<div class="content-sections">
<div :class="{
'content-section': lesson.id != lessonid,
'content-section content-section-choose': lesson.id == lessonid,
}"
v-for="(lesson , index) in section.courseLessons" :key="index"
@click="playLesson(1,index,lesson)"
>
<!-- 第一章,前两节 -->
<div v-if="index<2">
<div class="section-item clearfix">
<span :class="{
'kw-icon-video section-type-icon': lesson.id != lessonid,
'kw-icon-video section-type-icon lv': lesson.id == lessonid,
}"><i class="el-icon-video-play"></i></span>
<span :class="{
'section-dec': lesson.id != lessonid,
'section-dec lv': lesson.id == lessonid,
}">{{lesson.theme}}</span>
<span v-if="lesson.id != lessonid" class="section-status-icon pause-play">试看</span>
<span v-else class="section-status-icon pause-play"></span>
</div>
<div class="section-duration">
<span v-if="lesson.courseMedia != null">时长:{{lesson.courseMedia.duration}}</span>
<span v-else>时长:无媒体文件</span>
</div>
</div>
<div v-if="index>1">
<div class="section-item clearfix">
<span :class="{
'kw-icon-video section-type-icon': lesson.id != lessonid,
'kw-icon-video section-type-icon lv': lesson.id == lessonid,
}"><i class="el-icon-video-play"></i></span>
<span :class="{
'section-dec': lesson.id != lessonid,
'section-dec lv': lesson.id == lessonid,
}">{{lesson.theme}}</span>
<!-- 未登录 => 锁 -->
<span v-if="!isLogin" class="section-status-icon pause-play">未解锁</span>
<!-- 已登录,未购买 => 锁 -->
<span v-else-if="isLogin && !isBuy" class="section-status-icon pause-play">未解锁</span>
<!-- 已登录,已购买 => 播放 -->
<span v-else-if="lesson.id != lessonid" class="section-status-icon pause-play">播放</span>
<span v-else-if="lesson.id == lessonid" class="section-status-icon pause-play"></span>
</div>
<div class="section-duration">
<span v-if="lesson.courseMedia != null">时长:{{lesson.courseMedia.duration}}</span>
<span v-else>时长:无媒体文件</span>
</div>
</div>
</div>
<!-- 正在播放的视频
<div class="content-section content-section-choose"
style=" color: #00b38a;" >
<div class="section-item clearfix">
<span class="kw-icon-video section-type-icon lv"><i class="el-icon-video-play"></i></span>
<span class="section-dec lv">2.起步</span>
<span class="section-status-icon pause-play"></span>
</div>
<div class="section-duration">
<span>时长:0</span>
</div>
</div>
-->
</div>
</div>
<!-- 第一章 结束 -->
<!-- 其余章 开始 -->
<div v-for="section in course.courseSections.slice(1,course.courseSections.length)">
<div class="content-label">
<div class="content-label-title single-line">{{section.sectionName}}</div>
<img
class="arrow-icon"
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkBAMAAAATLoWrAAAAGFBMVEVHcEz///////////////////////////8dS1W+AAAAB3RSTlMAgwWyMeGgBsFrrQAAAFVJREFUKM9jYBiugMUBQ0i8EF2EsbxcAF1ReXkhuqJiczRl4uVGyqjKgIoUmFCVARUxMKAoAyliYEBRBlaEqiwcpAikrBShKglCqyFUMcEYCgwjBAAAeaoQrHtg6QoAAAAASUVORK5CYII="
alt=""
/>
</div>
<div class="content-sections">
<div :class="{
'content-section': lesson.id != lessonid,
'content-section content-section-choose': lesson.id == lessonid,
}"
v-for="(lesson , index) in section.courseLessons"
:key="index"
@click="playLesson(2,index,lesson)"
>
<div>
<div class="section-item clearfix">
<span :class="{
'kw-icon-video section-type-icon': lesson.id != lessonid,
'kw-icon-video section-type-icon lv': lesson.id == lessonid,
}"><i class="el-icon-video-play"></i></span>
<span :class="{
'section-dec': lesson.id != lessonid,
'section-dec lv': lesson.id == lessonid,
}">{{lesson.theme}}</span>
<!-- 未登录 => 锁 -->
<span v-if="!isLogin" class="section-status-icon pause-play">未解锁</span>
<!-- 已登录,未购买 => 锁 -->
<span v-else-if="isLogin && !isBuy" class="section-status-icon pause-play">未解锁</span>
<!-- 已登录,已购买 => 播放 -->
<span v-else-if="lesson.id != lessonid" class="section-status-icon pause-play">播放</span>
<span v-else-if="lesson.id == lessonid" class="section-status-icon pause-play"></span>
</div>
<div class="section-duration">
<span v-if="lesson.courseMedia != null">时长:{{lesson.courseMedia.duration}}</span>
<span v-else>时长:无媒体文件</span>
</div>
</div>
</div>
</div>
</div>
<!-- 其余章 结束 -->
</div>
</div>
</div>
</div>
</div>
</div>
<script>
export default {
name: "videoDetail",
components: {},
data() {
return {
myvideo: null, // 播放器对象
isplay: false, //是否在播放
nowTime: "00:00", //当前播放时间
totalTime: "00:00", //总时长
course:null, // 课程
lessonid:0, // 当前播放视频的课节id
lessonName:null, // 当前播放的视频名称
isLogin:false, // false 未登录
isBuy:false, // false 未购买
};
},
computed: {},
created() {
// 判断登录(暂无)
this.user = JSON.parse(localStorage.getItem("user"));
if(this.user != null){
this.isLogin = true; // 已登录
}
// 从上一级页面的请求中获得课程对象和小节编号
this.course = this.$route.params.course;
this.lessonid = this.$route.params.lessonid;
this.isBuy = this.$route.params.isBuy;
},
mounted() {
this.myvideo = document.getElementById("myvideo");
this.myvideo.controls = true; // 显示播放器的控制面板
this.initplay(); // 初始化播放的视频
},
methods: {
play() {
this.isplay = !this.isplay;
if (this.isplay) {
this.myvideo.play();
} else {
this.myvideo.pause();
}
},
// 获取视频的时间是秒为单位,格式化城00:00的格式
formatTime(time) {
let mm = Math.floor((time % 3600) / 60);
let ss = Math.floor(time % 60);
mm = mm < 10 ? "0" + mm : mm;
ss = ss < 10 ? "0" + ss : ss;
return `${mm}:${ss}`;
},
//获取初始化信息
getInit() {
if (!this.myvideo) {
//获取失败,显示0
this.totalTime = this.formatTime(0);
} else {
//获取视频总时长
this.totalTime = this.formatTime(this.myvideo.duration);
}
},
//播放时显示当前播放时间和总时长
handlerNowTime() {
if (!this.myvideo) {
this.nowTime = `${this.formatTime(0)}`;
}
this.nowTime = this.formatTime(this.myvideo.currentTime || 0);
},
//返回
goBack() {
this.$router.push({ name: "Course", params: { course: this.course } });
},
//播放课程
playLesson(status,index,lesson) {
if(lesson.courseMedia == null){
this.$message.error("播放失败,暂无视频!");
}else{
// 试看的可以跳转播放页面
if(status == 1 && index < 2){
this.playNow(lesson);
}else{ // 锁上的,先验证是否登录
if(!this.isLogin){
this.$message.success("请先登录!");
}else{ // 登录后,再验证是否购买过
if(!this.isBuy){
this.$message.warning("请购买并解锁,才能观看本视频!");
}else{
this.playNow(lesson);
}
}
}
}
},
playNow(lesson){
this.lessonid = lesson.id; // 当前播放的视频,就是我点击的课
this.myvideo.src = lesson.courseMedia.fileEdk; // 切换播放器的播放地址
this.myvideo.play(); // 立刻播放
this.isplay = true; // 按钮呈现为播放状态
},
// 初始化时播放的视频
initplay(){
//1.在课程信息中查找即将播放的小节视频的编号
for( let i = 0 ; i< this.course.courseSections.length;i++ ){
let section = this.course.courseSections[i];
for(let j = 0; j<section.courseLessons.length ; j++){
let lesson = section.courseLessons[j]; // 每节课
if(lesson.courseMedia!=null){
if(this.lessonid == lesson.courseMedia.lessonId){
console.log("视频地址:" + lesson.courseMedia.fileEdk);
this.lessonName = lesson.theme;
//2.将小节视频的地址 赋值 给播放器,进行播放
this.myvideo.src = lesson.courseMedia.fileEdk;
return;
}
}
}
}
}
},
};
</script>