|
@@ -1,7 +1,64 @@
|
|
|
<template>
|
|
|
<div class="living-room">
|
|
|
<Header></Header>
|
|
|
+
|
|
|
<div class="container">
|
|
|
+ <div class="clearfix top-line">
|
|
|
+ <el-button
|
|
|
+ class="float-right"
|
|
|
+ type="primary"
|
|
|
+ size="small"
|
|
|
+ round
|
|
|
+ @click="$router.back(-1)"
|
|
|
+ >返回</el-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ <!-- pc端 -->
|
|
|
+ <div class="plv-watch-pc">
|
|
|
+ <div class="plv-watch-pc__top" id="plv-pc-top">
|
|
|
+ <div class="plv-watch-pc__screen plv-watch-pc__screen-main">
|
|
|
+ <div class="plv-watch-pc__screen__height">
|
|
|
+ <div class="plv-watch-pc__screen__inner" id="plv-pc-main"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="plv-watch-pc__screen plv-watch-pc__screen-sub">
|
|
|
+ <div class="plv-watch-pc__screen__height">
|
|
|
+ <div class="plv-watch-pc__screen__inner" id="plv-pc-side"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="plv-watch-pc__side">
|
|
|
+ <div
|
|
|
+ class="plv-watch-pc__chat plv-skin--dark"
|
|
|
+ id="plv-pc-chat"
|
|
|
+ ></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div id="plv-pc-channel-info" class="plv-watch-pc__info">
|
|
|
+ <img
|
|
|
+ class="plv-watch-pc__info__logo"
|
|
|
+ src="https://live.polyv.cn/assets/wimages/pc_images/logo.png"
|
|
|
+ />
|
|
|
+ <div class="plv-watch-pc__info__desc">
|
|
|
+ <p class="plv-watch-pc__info__desc__name"></p>
|
|
|
+ <span class="plv-watch-pc__info__desc__publisher-ico"></span>
|
|
|
+ <span class="plv-watch-pc__info__desc__publisher"></span>
|
|
|
+ <span class="plv-watch-pc__info__desc__view"></span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- pc菜单栏 -->
|
|
|
+ <!-- <div class="plv-pc-menu">
|
|
|
+ <div class="plv-pc-menu__container">
|
|
|
+ <ul id="plv-menu-tab" class="plv-pc-menu__tab"></ul>
|
|
|
+ <div id="plv-menu-content" class="plv-pc-menu__content"></div>
|
|
|
+ </div>
|
|
|
+ </div> -->
|
|
|
+ </div>
|
|
|
+ <!-- <div class="container">
|
|
|
<div ref="living" id="living" class="living">
|
|
|
<div
|
|
|
:style="
|
|
@@ -31,7 +88,7 @@
|
|
|
<div ref="wrap" id="wrap"></div>
|
|
|
<div class="controller" ref="controller"></div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
+ </div> -->
|
|
|
<Footer></Footer>
|
|
|
</div>
|
|
|
</template>
|
|
@@ -41,7 +98,11 @@ import Footer from "@/components/footer/index";
|
|
|
import Header from "@/components/header/index";
|
|
|
import ToolBar from "@/components/toolbar/index";
|
|
|
import { mapGetters, mapMutations } from "vuex";
|
|
|
+import "@/assets/jquery.min.js";
|
|
|
import "@/assets/css/chatroom.css";
|
|
|
+import "@/assets/css/pc.css";
|
|
|
+import "@/assets/css/tool.css";
|
|
|
+import "@/assets/css/public.css";
|
|
|
|
|
|
export default {
|
|
|
components: {
|
|
@@ -58,16 +119,41 @@ export default {
|
|
|
appId: "",
|
|
|
sign: "",
|
|
|
timestamp: "",
|
|
|
+ timer: null,
|
|
|
mediaChannelKey: "",
|
|
|
changeState: false,
|
|
|
liveSdk: null,
|
|
|
token: "",
|
|
|
+ plv: {
|
|
|
+ liveSdk: null, // 保存直播 JS-SDK 实例
|
|
|
+ socket: null, // 保存 WebSocket 实例
|
|
|
+ scene: "", // 场景
|
|
|
+ mainPosition: "player", // 用于记录当前主屏幕是文档还是播放器
|
|
|
+ },
|
|
|
+ sectionId: 0,
|
|
|
+ goodsId: 0,
|
|
|
+ courseId: 0,
|
|
|
+ orderGoodsId: 0,
|
|
|
+ gradeId: 0,
|
|
|
+ chapterId: 0,
|
|
|
+ moduleId: 0,
|
|
|
+ playTime: 0,
|
|
|
+ duraing: 0,
|
|
|
+ timer: null,
|
|
|
+ isFirst: true,
|
|
|
};
|
|
|
},
|
|
|
computed: {
|
|
|
...mapGetters(["userInfo"]),
|
|
|
},
|
|
|
mounted() {
|
|
|
+ this.sectionId = this.$route.query.sectionId;
|
|
|
+ this.goodsId = this.$route.query.goodsId;
|
|
|
+ this.courseId = this.$route.query.courseId;
|
|
|
+ this.orderGoodsId = this.$route.query.orderGoodsId;
|
|
|
+ this.gradeId = this.$route.query.gradeId;
|
|
|
+ this.chapterId = this.$route.query.chapterId;
|
|
|
+ this.moduleId = this.$route.query.moduleId;
|
|
|
this.channelId = this.$route.params.channelId;
|
|
|
this.playVideo();
|
|
|
},
|
|
@@ -93,13 +179,39 @@ export default {
|
|
|
},
|
|
|
|
|
|
async playVideo() {
|
|
|
+ // await this.jquery();
|
|
|
await this.loadPlayerScriptzb();
|
|
|
await this.loadChatroomScriptzb();
|
|
|
console.log(this.userInfo);
|
|
|
this.polyvLivesign();
|
|
|
},
|
|
|
|
|
|
+ jquery() {
|
|
|
+ return new Promise((resolve) => {
|
|
|
+ if (!window.polyvLivePlayer) {
|
|
|
+ const myScript = document.createElement("script");
|
|
|
+ myScript.setAttribute("src", "../../assets/jquery.min.js");
|
|
|
+ document.body.appendChild(myScript);
|
|
|
+ myScript.onload = resolve;
|
|
|
+ } else {
|
|
|
+ resolve();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
loadPlayerzb() {
|
|
|
+ var els = {
|
|
|
+ playerEl: "", // 播放器容器选择器, 移动端和PC的el参数设置不
|
|
|
+ pptEl: "", // 文档容器选择器, 普通直播不需要设置pptEl
|
|
|
+ controllerEl: "", // 三分屏控制栏的容器选择器, pc三分屏的场景才需要设置controllerEl,
|
|
|
+ chatContainer: "", // 聊天室的容器选择器
|
|
|
+ pptEl: "#tab-ppt",
|
|
|
+ };
|
|
|
+
|
|
|
+ els.chatContainer = "#plv-pc-chat"; // DOM选择器,HTML元素,用于渲染聊天室
|
|
|
+ els.pptEl = "#plv-pc-side"; // ppt文档元素选择器,非云课堂可不填
|
|
|
+ els.playerEl = "#plv-pc-main"; // 讲师区域元素
|
|
|
+ els.controllerEl = $("#plv-pc-top")[0]; // 控制栏父元素
|
|
|
var chatroom = new PolyvChatRoom({
|
|
|
//实例聊天室SDK
|
|
|
roomId: this.channelId,
|
|
@@ -109,24 +221,29 @@ export default {
|
|
|
pic:
|
|
|
this.$tools.splitImgHost(this.userInfo.avatar, true) ||
|
|
|
"http://livestatic.videocc.net/assets/wimages/missing_face.png",
|
|
|
- container: "#wrap",
|
|
|
+ container: els.chatContainer,
|
|
|
userType: "slice",
|
|
|
version: "2.0",
|
|
|
showUserList: false,
|
|
|
- width: 300,
|
|
|
- height: 400,
|
|
|
+ width: "100%",
|
|
|
+ height: "100%",
|
|
|
token: this.token,
|
|
|
mediaChannelKey: this.mediaChannelKey,
|
|
|
roomMessage: (data) => {
|
|
|
// data为聊天室socket消息,当有聊天室消息时会触发此方法
|
|
|
- if (this.liveSdk && this.liveSdk.player) {
|
|
|
- console.log(data.content);
|
|
|
- this.liveSdk.player.sendBarrage(data.content);
|
|
|
+ console.log(data);
|
|
|
+ if (this.plv.liveSdk && this.plv.liveSdk.player) {
|
|
|
+ var event = data.EVENT;
|
|
|
+ if (event === "sendMessage" || event === "SPEAK") {
|
|
|
+ this.plv.liveSdk.player.sendBarrage(data.content);
|
|
|
+ }
|
|
|
}
|
|
|
},
|
|
|
});
|
|
|
|
|
|
- var liveSdk = new PolyvLiveSdk({
|
|
|
+ this.plv.socket = chatroom.chat.socket;
|
|
|
+
|
|
|
+ this.plv.liveSdk = new PolyvLiveSdk({
|
|
|
//实例直播SDK
|
|
|
channelId: this.channelId,
|
|
|
appId: this.appId,
|
|
@@ -142,38 +259,98 @@ export default {
|
|
|
},
|
|
|
});
|
|
|
|
|
|
- this.liveSdk = liveSdk;
|
|
|
+ this.plv.liveSdk.on(
|
|
|
+ PolyvLiveSdk.EVENTS.STREAM_UPDATE,
|
|
|
+ (event, status) => {
|
|
|
+ if (status == "end") {
|
|
|
+ clearInterval(this.timer);
|
|
|
+ let duraing = this.playTime - this.duraing;
|
|
|
+ this.duraing = 0;
|
|
|
+ this.studyRecord(1, duraing);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ); // 监听流状态变化
|
|
|
|
|
|
// 第四步:监听频道信息读取完成事件,初始化播放器
|
|
|
- liveSdk.on(PolyvLiveSdk.EVENTS.CHANNEL_DATA_INIT, (event, data) => {
|
|
|
- liveSdk.setupPlayer({
|
|
|
- pptEl: "#ppt",
|
|
|
- el: "#player",
|
|
|
- type: "auto",
|
|
|
- switchPlayer: true,
|
|
|
- controllerPosition: "ppt",
|
|
|
- pptNavBottom: "180px",
|
|
|
- controllerPosition: "player",
|
|
|
- fixedController: true,
|
|
|
- barrage: true,
|
|
|
- defaultBarrageStatus: true,
|
|
|
- controllerEl: this.$refs.controller,
|
|
|
- fullscreenEl: this.$refs.ppt,
|
|
|
- autoplay: true, // 设置自动播放
|
|
|
- });
|
|
|
+ this.plv.liveSdk.on(
|
|
|
+ PolyvLiveSdk.EVENTS.CHANNEL_DATA_INIT,
|
|
|
+ (event, data) => {
|
|
|
+ this.plv.liveSdk.setupPlayer({
|
|
|
+ el: els.playerEl,
|
|
|
+ pptEl: els.pptEl,
|
|
|
+ pptPlaceholder: true,
|
|
|
+ switchPlayer: true,
|
|
|
+ controllerPosition: "ppt",
|
|
|
+ fixedController: true,
|
|
|
+ controllerEl: els.controllerEl,
|
|
|
+ pptNavBottom: "80px",
|
|
|
+ barrage: true, // 是否开启弹幕
|
|
|
+ defaultBarrageStatus: true,
|
|
|
+ autoplay: true,
|
|
|
+ });
|
|
|
|
|
|
- liveSdk.player.on("switchPlayer", () => {
|
|
|
- this.changeState = !this.changeState;
|
|
|
- if (this.changeState) {
|
|
|
- liveSdk.player.setFullscreenEl(this.$refs.ppt);
|
|
|
- } else {
|
|
|
- liveSdk.player.setFullscreenEl(this.$refs.player);
|
|
|
- }
|
|
|
- });
|
|
|
+ this.plv.liveSdk.player.on(
|
|
|
+ "fullscreenChange",
|
|
|
+ this.handleFullscreenChange
|
|
|
+ );
|
|
|
+ this.plv.liveSdk.player.on("switchPlayer", this.handleSwitchPlayer); // 点击控制栏切换按钮触发
|
|
|
+ this.plv.liveSdk.player.on("switchMainScreen", this.switchPlayer);
|
|
|
|
|
|
- liveSdk.player.on("switchMainScreen", (main) => {
|
|
|
- console.log("切换主讲位置,当前主屏为", main); // 'player'|'ppt'
|
|
|
- });
|
|
|
+ // this.plv.liveSdk.player.on("switchPlayer", () => {
|
|
|
+ // var switchPosition = plv.mainPosition === 'ppt' ? 'player' : 'ppt';
|
|
|
+ // switchPlayer(switchPosition);
|
|
|
+ // });
|
|
|
+
|
|
|
+ // this.plv.liveSdk.player.on("switchMainScreen", (main) => {
|
|
|
+ // console.log("切换主讲位置,当前主屏为", main); // 'player'|'ppt'
|
|
|
+ // });
|
|
|
+
|
|
|
+ // this.plv.liveSdk.player.on("ended", () => {
|
|
|
+ // this.duraing += this.playTime;
|
|
|
+ // clearInterval(this.timer);
|
|
|
+ // this.studyRecord(1);
|
|
|
+ // });
|
|
|
+
|
|
|
+ this.plv.liveSdk.player.on("pause", (state) => {
|
|
|
+ let duraing = this.playTime - this.duraing;
|
|
|
+ this.duraing = 0;
|
|
|
+ this.studyRecord(0, duraing);
|
|
|
+ clearInterval(this.timer);
|
|
|
+ });
|
|
|
+
|
|
|
+ this.plv.liveSdk.player.on("loadedmetadata", (state) => {
|
|
|
+ if (this.isFirst) {
|
|
|
+ this.studyRecord(0);
|
|
|
+ this.isFirst = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ clearInterval(this.timer);
|
|
|
+ this.timer = setInterval(() => {
|
|
|
+ this.studyRecord(0, 20);
|
|
|
+ this.duraing += 20;
|
|
|
+ }, 20000);
|
|
|
+ });
|
|
|
+
|
|
|
+ this.plv.liveSdk.player.on("timeupdate", (time) => {
|
|
|
+ this.playTime = time;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ );
|
|
|
+ },
|
|
|
+
|
|
|
+ studyRecord(status, duraing) {
|
|
|
+ let self = this;
|
|
|
+ this.$request.studyRecord({
|
|
|
+ sectionId: parseInt(this.sectionId),
|
|
|
+ goodsId: parseInt(self.goodsId),
|
|
|
+ courseId: parseInt(self.courseId),
|
|
|
+ orderGoodsId: this.orderGoodsId,
|
|
|
+ studyDuration: parseInt(duraing) || 0,
|
|
|
+ gradeId: parseInt(self.gradeId),
|
|
|
+ chapterId: parseInt(self.chapterId),
|
|
|
+ moduleId: parseInt(self.moduleId),
|
|
|
+ videoCurrentTime: 2,
|
|
|
+ status: status,
|
|
|
});
|
|
|
},
|
|
|
/**
|
|
@@ -206,6 +383,59 @@ export default {
|
|
|
}
|
|
|
});
|
|
|
},
|
|
|
+
|
|
|
+ handleSwitchPlayer() {
|
|
|
+ var switchPosition = this.plv.mainPosition === "ppt" ? "player" : "ppt";
|
|
|
+ this.switchPlayer(switchPosition);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 控制栏切换按钮的点击处理函数,仅适用PC端
|
|
|
+ handleSwitchPlayer() {
|
|
|
+ var switchPosition = this.plv.mainPosition === "ppt" ? "player" : "ppt";
|
|
|
+ this.switchPlayer(switchPosition);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 点击到文档tab时调用播放器的resize方法,原因:
|
|
|
+ // ppt父容器样式改变会导致ppt显示异常,需要调用resize刷新ppt尺寸,该函数用于移动端三分屏场景
|
|
|
+ handlePptTabClick() {
|
|
|
+ $("[data-type=ppt]").click(function () {
|
|
|
+ setTimeout(function () {
|
|
|
+ this.plv.liveSdk.player.resize();
|
|
|
+ }, 0);
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // 全屏/退出全屏回调
|
|
|
+ handleFullscreenChange(isFullScreen, fullScreenElement) {
|
|
|
+ if (isFullScreen) {
|
|
|
+ $(fullScreenElement).addClass("plv-watch-pc__top--fullscreen");
|
|
|
+ } else {
|
|
|
+ $(fullScreenElement).removeClass("plv-watch-pc__top--fullscreen");
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 切换主副屏,如需兼容ie,建议通过css的方式去切换位置,dom操作可能导致播放器异常
|
|
|
+ switchPlayer(nextMainPosition) {
|
|
|
+ var pcScreens = $(".plv-watch-pc__screen").removeClass(
|
|
|
+ "plv-watch-pc__screen-main plv-watch-pc__screen-sub"
|
|
|
+ );
|
|
|
+
|
|
|
+ switch (nextMainPosition) {
|
|
|
+ case "player":
|
|
|
+ pcScreens.eq(0).addClass("plv-watch-pc__screen-sub");
|
|
|
+ pcScreens.eq(1).addClass("plv-watch-pc__screen-main");
|
|
|
+ break;
|
|
|
+
|
|
|
+ case "ppt":
|
|
|
+ pcScreens.eq(0).addClass("plv-watch-pc__screen-main");
|
|
|
+ pcScreens.eq(1).addClass("plv-watch-pc__screen-sub");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.plv.mainPosition = nextMainPosition;
|
|
|
+ this.plv.liveSdk.player.resize(); // ppt容器宽高修改,调用resize刷新ppt尺寸
|
|
|
+ this.plv.liveSdk.player.resizeBarrage(); // 刷新弹幕显示区域尺寸
|
|
|
+ },
|
|
|
},
|
|
|
};
|
|
|
</script>
|
|
@@ -214,6 +444,17 @@ export default {
|
|
|
<style scoped lang="scss">
|
|
|
.living-room {
|
|
|
background: #eee;
|
|
|
+ .container {
|
|
|
+ margin: 10px auto;
|
|
|
+ }
|
|
|
+ .top-line {
|
|
|
+ margin: 10px 0;
|
|
|
+ .float-right {
|
|
|
+ float: right;
|
|
|
+ width: 100px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
.living {
|
|
|
position: relative;
|
|
|
width: 900px;
|