index.vue 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950
  1. <template>
  2. <div class="living-room">
  3. <Header></Header>
  4. <div class="container">
  5. <div class="clearfix top-line">
  6. <div class="title">{{ goodsName }}</div>
  7. <div class="bottoms">
  8. <el-button
  9. size="small"
  10. round
  11. @click="toShare()"
  12. >分享</el-button>
  13. <el-button
  14. class="float-right"
  15. type="primary"
  16. size="small"
  17. round
  18. @click="returnBack()"
  19. >返回</el-button
  20. >
  21. </div>
  22. </div>
  23. </div>
  24. <!-- pc端 -->
  25. <div class="plv-watch-pc">
  26. <div class="plv-watch-pc__top" id="plv-pc-top">
  27. <div class="plv-watch-pc__screen plv-watch-pc__screen-main">
  28. <div class="plv-watch-pc__screen__height">
  29. <div class="plv-watch-pc__screen__inner" id="plv-pc-main"></div>
  30. </div>
  31. </div>
  32. <div class="plv-watch-pc__screen plv-watch-pc__screen-sub">
  33. <div class="plv-watch-pc__screen__height">
  34. <div class="plv-watch-pc__screen__inner" id="plv-pc-side"></div>
  35. </div>
  36. </div>
  37. <div class="plv-watch-pc__side">
  38. <div class="plv-watch-pc__chat plv-skin--dark" id="plv-pc-chat"></div>
  39. </div>
  40. </div>
  41. <div id="plv-pc-channel-info" class="plv-watch-pc__info">
  42. <img
  43. class="plv-watch-pc__info__logo"
  44. src="https://live.polyv.cn/assets/wimages/pc_images/logo.png"
  45. />
  46. <div class="plv-watch-pc__info__desc">
  47. <p class="plv-watch-pc__info__desc__name"></p>
  48. <span class="plv-watch-pc__info__desc__publisher-ico"></span>
  49. <span class="plv-watch-pc__info__desc__publisher"></span>
  50. <span class="plv-watch-pc__info__desc__view"></span>
  51. </div>
  52. </div>
  53. </div>
  54. <!-- pc菜单栏 -->
  55. <!-- <div class="plv-pc-menu">
  56. <div class="plv-pc-menu__container">
  57. <ul id="plv-menu-tab" class="plv-pc-menu__tab"></ul>
  58. <div id="plv-menu-content" class="plv-pc-menu__content"></div>
  59. </div>
  60. </div> -->
  61. <!-- </div> -->
  62. <!-- <div class="container">
  63. <div ref="living" id="living" class="living">
  64. <div
  65. :style="
  66. changeState
  67. ? { left: 0, top: 0, width: 600 + 'px', height: 600 + 'px' }
  68. : {}
  69. "
  70. id="ppt"
  71. ref="ppt"
  72. class="ppt"
  73. ></div>
  74. <div
  75. :style="
  76. changeState
  77. ? {
  78. left: 600 + 'px',
  79. top: 0,
  80. width: 300 + 'px',
  81. height: 200 + 'px',
  82. }
  83. : {}
  84. "
  85. id="player"
  86. ref="player"
  87. class="player"
  88. ></div>
  89. <div ref="wrap" id="wrap"></div>
  90. <div class="controller" ref="controller"></div>
  91. </div>
  92. </div> -->
  93. <Footer></Footer>
  94. <el-dialog
  95. width="462px"
  96. class="sign-modal"
  97. :visible.sync="signModal"
  98. :close-on-click-modal="false"
  99. :close-on-press-escape="false"
  100. :show-close="false"
  101. >
  102. <div class="sign-modal__content">
  103. <img class="img" src="@/assets/sign.png" alt="" />
  104. <div class="box">
  105. <div class="title">直播已经开始啦,赶紧签到进入直播吧!</div>
  106. <el-button type="primary" class="btn" @click="close"
  107. >立即签到</el-button
  108. >
  109. </div>
  110. </div>
  111. </el-dialog>
  112. <el-dialog
  113. width="400px"
  114. :visible.sync="signSuccess"
  115. :close-on-click-modal="false"
  116. :close-on-press-escape="false"
  117. :show-close="false"
  118. >
  119. <div class="sign-success__content">
  120. <img class="img" src="@/assets/appoinsuccess.png" alt="" />
  121. <div class="title">签到成功!</div>
  122. </div>
  123. </el-dialog>
  124. <!-- 您还没有开通直播课程,无法观看 -->
  125. <el-dialog
  126. title="提示"
  127. :visible.sync="showAuth"
  128. :close-on-click-modal="false"
  129. :close-on-press-escape="false"
  130. :show-close="false"
  131. width="400px"
  132. >
  133. <div class="popCentent">
  134. <div class="tips">您还没有开通直播课程,无法观看</div>
  135. <div class="btns" @click="toAuth()">立即开通</div>
  136. </div>
  137. </el-dialog>
  138. <!-- 分享弹窗 -->
  139. <el-dialog
  140. title="提示"
  141. :visible.sync="shareShow"
  142. width="600px"
  143. >
  144. <div v-loading="shareLoading" class="popShare">
  145. <el-form ref="form" :model="formShare" label-width="130px">
  146. <el-form-item label="观看链接(pc端):">
  147. <div>
  148. <span>{{ formShare.links }}</span>
  149. <span class="ccopy" @click="copy()">复制</span>
  150. </div>
  151. </el-form-item>
  152. <el-form-item label="观看二维码:">
  153. <img class="ercode_pic" :src="formShare.ercode" alt="" />
  154. <span class="ccopy" @click="download()">下载</span>
  155. </el-form-item>
  156. </el-form>
  157. </div>
  158. </el-dialog>
  159. </div>
  160. </template>
  161. <script>
  162. import Footer from "@/components/footer/index";
  163. import Header from "@/components/header/index";
  164. import ToolBar from "@/components/toolbar/index";
  165. import { mapGetters, mapMutations } from "vuex";
  166. import "@/assets/jquery.min.js";
  167. import "@/assets/css/chatroom.css";
  168. import "@/assets/css/pc.css";
  169. import "@/assets/css/tool.css";
  170. import "@/assets/css/public.css";
  171. let Base64 = require('js-base64').Base64
  172. export default {
  173. components: {
  174. Footer,
  175. Header,
  176. ToolBar,
  177. },
  178. data() {
  179. return {
  180. signSuccess: false,
  181. signModal: false,
  182. playerJs: "https://player.polyv.net/livesdk/polyv-live.min.js",
  183. chatroomJs: "https://player.polyv.net/jssdk/polyv-chatroom.min.js",
  184. uidzb: "egsxlptzdq",
  185. channelId: "",
  186. appId: "",
  187. sign: "",
  188. timestamp: "",
  189. timer: null,
  190. mediaChannelKey: "",
  191. changeState: false,
  192. liveSdk: null,
  193. token: "",
  194. plv: {
  195. liveSdk: null, // 保存直播 JS-SDK 实例
  196. socket: null, // 保存 WebSocket 实例
  197. scene: "", // 场景
  198. mainPosition: "player", // 用于记录当前主屏幕是文档还是播放器
  199. },
  200. sectionId: 0,
  201. goodsId: 0,
  202. courseId: 0,
  203. orderGoodsId: 0,
  204. gradeId: 0,
  205. chapterId: 0,
  206. moduleId: 0,
  207. playTime: 0,
  208. duraing: 0,
  209. timer: null,
  210. liveLast: null,
  211. isFirst: true,
  212. backNum: -1, //返回页面数
  213. buyCourse: 1, // 是否购买课程:1是 0否
  214. identification: '', // 标识
  215. goodsName: '', // 名称
  216. checkStatus: 0, // 0没有权限,1有权限
  217. goodsStatus: 0, // 0未上架,1上架
  218. showAuth: false,
  219. shareShow: false,
  220. sectionType: 2, //sectionType: 2, // 节类型 1录播 2直播 3回放
  221. vid: '', // 回放的id
  222. formShare: {
  223. links: '',
  224. ercode: '',
  225. },
  226. shareLoading: false
  227. };
  228. },
  229. computed: {
  230. ...mapGetters(["userInfo"]),
  231. },
  232. beforeRouteEnter(to, from, next) {
  233. next((vm) => {
  234. if (from.path.includes("my-course-detail")) {
  235. vm.backNum = -2;
  236. } else if (from.path == '/login') {
  237. vm.backNum = 0;
  238. } else {
  239. vm.backNum = -1;
  240. }
  241. });
  242. },
  243. created() {
  244. console.log('是否登录了', this.$route.query)
  245. if (!this.$tools.isLogin()) {
  246. this.setCurrentRouter(this.$route);
  247. this.$router.push({
  248. path: "/login",
  249. });
  250. return;
  251. }
  252. const { a } = this.$route.query
  253. console.log('aaaaaaaaa', a, decodeURIComponent(location.search.slice(5)))
  254. this.channelId = this.$route.params.channelId
  255. // 有a字段是标识是复制链接进来
  256. if (a ==1) {
  257. this.getParam()
  258. return
  259. }
  260. // 下面不是复制链接进来的
  261. const {sectionId, goodsId, courseId, orderGoodsId, gradeId, chapterId, moduleId, goodsName, sectionType, vid} = this.$route.query
  262. this.sectionId = sectionId
  263. this.goodsId = goodsId
  264. this.courseId = courseId
  265. this.orderGoodsId = orderGoodsId
  266. this.gradeId = +gradeId
  267. this.chapterId = chapterId
  268. this.moduleId = moduleId
  269. // this.channelId = this.$route.params.channelId;
  270. this.goodsName = goodsName
  271. this.sectionType = sectionType
  272. this.vid = vid
  273. this.identification = new Date().valueOf() + ""
  274. this.buyCourse = 0
  275. this.playVideo();
  276. if (this.sectionType !=3 ) {
  277. this.studyRecordGetLastLive();
  278. }
  279. },
  280. beforeDestroy() {
  281. if (!this.$tools.isLogin()) return
  282. this.plv.liveSdk.destroy();
  283. clearInterval(this.timer);
  284. },
  285. methods: {
  286. ...mapMutations(["setCurrentRouter", "getCartCount"]),
  287. returnBack() {
  288. console.log('backNum', this.backNum)
  289. if (this.backNum == 0) {
  290. this.$router.push({
  291. path: '/home'
  292. })
  293. } else {
  294. this.$router.go(this.backNum)
  295. }
  296. },
  297. toShare() {
  298. this.shareLoading = true
  299. this.shareShow = true
  300. this.$axios({
  301. url: '/course/watch/per',
  302. method: 'get',
  303. params: {
  304. courseId: this.courseId, //课程ID
  305. goodsId: this.goodsId, // 商品id
  306. moduleId: this.moduleId || null,
  307. chapterId: this.chapterId || null,
  308. sectionId: this.sectionId, // 节id
  309. sectionType: this.sectionType, //节类型 1录播 2直播 3回放
  310. },
  311. }).then((res) => {
  312. this.shareLoading = false
  313. if (res.code == 200) {
  314. this.formShare.links = res.data.enCodePC
  315. this.formShare.ercode = res.data.enCode
  316. }
  317. }).catch((err) => {
  318. this.shareLoading = false
  319. this.$message.warning(err.msg)
  320. })
  321. },
  322. // 获取直播间跳转参数的接口
  323. getParam() {
  324. let decodeValue = decodeURIComponent(location.search.slice(5))
  325. let paramArr = Base64.decode(decodeValue).split('&')
  326. console.log('paramArr:',paramArr)
  327. let paramObj = {}
  328. for (let i = 0; i < paramArr.length; i++) {
  329. paramObj[paramArr[i].split('=')[0]] = paramArr[i].split('=')[1]
  330. }
  331. const { cid, gid, sid} = paramObj
  332. console.log('cid, gid, sid', cid, gid, sid)
  333. this.$axios({
  334. url: '/course/check/watch/per',
  335. method: 'get',
  336. params: {
  337. courseId: cid, //课程ID
  338. goodsId: gid, // 商品id
  339. sectionId: sid, // 节id
  340. },
  341. }).then((res) => {
  342. if (res.code == 200) {
  343. let item = res.data
  344. const {sectionId, goodsId, courseId, orderGoodsId, gradeId, chapterId, moduleId, buyCourse, sectionType, recordingUrl} = item
  345. this.goodsId = goodsId
  346. this.sectionId = sectionId
  347. this.courseId = courseId
  348. this.orderGoodsId = orderGoodsId
  349. this.gradeId = +gradeId || 0
  350. this.chapterId = chapterId
  351. this.moduleId = moduleId
  352. this.buyCourse = buyCourse
  353. this.goodsStatus = item.goodsStatus
  354. this.goodsName = item.goodsName
  355. this.sectionType = sectionType
  356. this.vid = recordingUrl || ''
  357. console.log('vid', this.vid, this.sectionType)
  358. if (item.checkStatus == 1) { // 有权限
  359. this.identification = new Date().valueOf() + ""
  360. this.playVideo();
  361. if (this.sectionType != 3) {
  362. this.studyRecordGetLastLive();
  363. }
  364. } else {
  365. this.showAuth = true
  366. }
  367. }
  368. }).catch((err) => {
  369. console.log('500:', err)
  370. this.$message({
  371. message: err.msg,
  372. type: "warning",
  373. })
  374. this.$router.push({
  375. path: '/home'
  376. })
  377. })
  378. },
  379. toAuth() {
  380. if (this.goodsStatus == 1) { //已上架
  381. this.$router.push({
  382. path: "/course-detail/" + this.goodsId,
  383. })
  384. } else {
  385. this.$router.push({
  386. path: '/home'
  387. })
  388. }
  389. },
  390. // 新增用户视频学习日志
  391. studyLog() {
  392. this.$axios({
  393. url: '/user/study/log',
  394. method: 'post',
  395. data: {
  396. goodsId: this.goodsId,
  397. courseId: this.courseId,
  398. moduleId: this.moduleId || 0,
  399. chapterId: this.chapterId || 0,
  400. sectionId: this.sectionId || 0,
  401. fromPlat: 2, //来源平台 1小程序 2PC网站
  402. goodsType: 6, // 商品类型 1视频2题库 3补考 4前培 5虚拟赠送题库 6直播
  403. orderGoodsId: this.orderGoodsId,
  404. }
  405. }).then((res) => {
  406. console.log('直播的用户学习日志:', res)
  407. })
  408. },
  409. close() {
  410. this.signModal = false;
  411. this.signSuccess = true;
  412. setTimeout(() => {
  413. this.signSuccess = false;
  414. }, 1000);
  415. },
  416. polyvLivesign() {
  417. console.log(this.channelId);
  418. // /polyv/live/sign
  419. this.$request
  420. .polyvLivesign({
  421. channelId: this.channelId,
  422. })
  423. .then((res) => {
  424. if (res.code == 200) {
  425. this.sign = res.data.sign;
  426. this.token = res.data.token;
  427. this.mediaChannelKey = res.data.mediaChannelKey;
  428. this.timestamp = res.data.timestamp;
  429. this.appId = res.data.appId;
  430. this.loadPlayerzb();
  431. // 新增用户视频学习日志
  432. this.studyLog()
  433. } else {
  434. this.$message.warning(res.msg)
  435. }
  436. }).catch((err) => {
  437. this.$message.warning(err.msg)
  438. })
  439. },
  440. async playVideo() {
  441. // await this.jquery();
  442. await this.loadPlayerScriptzb();
  443. await this.loadChatroomScriptzb();
  444. console.log(this.userInfo);
  445. this.polyvLivesign();
  446. },
  447. /**
  448. * 获取上次观看的直播
  449. */
  450. studyRecordGetLastLive() {
  451. if (!this.gradeId && this.sectionId) {
  452. // /study/record/getLastLive
  453. this.$request
  454. .studyRecordGetLastLive({
  455. orderGoodsId: this.orderGoodsId,
  456. courseId: this.courseId,
  457. })
  458. .then((res) => {
  459. if (!res.data) {
  460. // this.signModal = true;
  461. }
  462. });
  463. }
  464. },
  465. jquery() {
  466. return new Promise((resolve) => {
  467. if (!window.polyvLivePlayer) {
  468. const myScript = document.createElement("script");
  469. myScript.setAttribute("src", "../../assets/jquery.min.js");
  470. document.body.appendChild(myScript);
  471. myScript.onload = resolve;
  472. } else {
  473. resolve();
  474. }
  475. });
  476. },
  477. loadPlayerzb() {
  478. var els = {
  479. playerEl: "", // 播放器容器选择器, 移动端和PC的el参数设置不
  480. pptEl: "", // 文档容器选择器, 普通直播不需要设置pptEl
  481. controllerEl: "", // 三分屏控制栏的容器选择器, pc三分屏的场景才需要设置controllerEl,
  482. chatContainer: "", // 聊天室的容器选择器
  483. pptEl: "#tab-ppt",
  484. };
  485. els.chatContainer = "#plv-pc-chat"; // DOM选择器,HTML元素,用于渲染聊天室
  486. els.pptEl = "#plv-pc-side"; // ppt文档元素选择器,非云课堂可不填
  487. els.playerEl = "#plv-pc-main"; // 讲师区域元素
  488. els.controllerEl = $("#plv-pc-top")[0]; // 控制栏父元素
  489. var chatroom = new PolyvChatRoom({
  490. //实例聊天室SDK
  491. roomId: this.channelId,
  492. userId: this.userInfo.userAccount,
  493. nick: this.userInfo.realname,
  494. accountId: this.userInfo.userAccount,
  495. pic:
  496. this.$tools.splitImgHost(this.userInfo.avatar, true) ||
  497. "http://livestatic.videocc.net/assets/wimages/missing_face.png",
  498. container: els.chatContainer,
  499. userType: "slice",
  500. version: "2.0",
  501. showUserList: false,
  502. width: "100%",
  503. height: "100%",
  504. token: this.token,
  505. mediaChannelKey: this.mediaChannelKey,
  506. roomMessage: (data) => {
  507. // data为聊天室socket消息,当有聊天室消息时会触发此方法
  508. console.log(data);
  509. if (this.plv.liveSdk && this.plv.liveSdk.player) {
  510. var event = data.EVENT;
  511. if (event === "sendMessage" || event === "SPEAK") {
  512. this.plv.liveSdk.player.sendBarrage(data.content);
  513. }
  514. }
  515. },
  516. });
  517. this.plv.socket = chatroom.chat.socket;
  518. this.plv.liveSdk = new PolyvLiveSdk({
  519. //实例直播SDK
  520. channelId: this.channelId,
  521. appId: this.appId,
  522. sign: this.sign,
  523. timestamp: this.timestamp,
  524. socket: chatroom.chat.socket, //传入聊天室的socket
  525. user: {
  526. userId: this.userInfo.userAccount,
  527. userName: this.userInfo.realname,
  528. pic:
  529. this.$tools.splitImgHost(this.userInfo.avatar, true) ||
  530. "http://livestatic.videocc.net/assets/wimages/missing_face.png",
  531. },
  532. });
  533. this.plv.liveSdk.on(
  534. PolyvLiveSdk.EVENTS.STREAM_UPDATE,
  535. (event, status) => {
  536. if (status == "end") {
  537. clearInterval(this.timer);
  538. let duraing = this.playTime - this.duraing;
  539. this.duraing = 0;
  540. this.studyRecord(1, duraing);
  541. }
  542. }
  543. ); // 监听流状态变化
  544. // 第四步:监听频道信息读取完成事件,初始化播放器
  545. let options = {
  546. el: els.playerEl,
  547. pptEl: els.pptEl,
  548. pptPlaceholder: true,
  549. switchPlayer: true,
  550. controllerPosition: "ppt",
  551. fixedController: true,
  552. controllerEl: els.controllerEl,
  553. pptNavBottom: "80px",
  554. barrage: true, // 是否开启弹幕
  555. defaultBarrageStatus: true,
  556. autoplay: true,
  557. }
  558. if (this.sectionType == 3) {
  559. // 回放模式需要fileId、url、sessionId
  560. // fileId: undefined, //ppt数据id,回放模式必填
  561. // url: undefined, // 回放视频链接,回放模式必填
  562. // sessionId: undefined, // 回放场次id,回放模式必填
  563. // vid: undefined, // 回放id,回放模式下传入该参数,可不传fileId、url、sessionId
  564. options.type = 'vod',
  565. options.vid = this.vid
  566. }
  567. console.log('options', options)
  568. this.plv.liveSdk.on(
  569. PolyvLiveSdk.EVENTS.CHANNEL_DATA_INIT,
  570. (event, data) => {
  571. this.plv.liveSdk.setupPlayer(options);
  572. this.plv.liveSdk.player.on(
  573. "fullscreenChange",
  574. this.handleFullscreenChange
  575. );
  576. this.plv.liveSdk.player.on("switchPlayer", this.handleSwitchPlayer); // 点击控制栏切换按钮触发
  577. this.plv.liveSdk.player.on("switchMainScreen", this.switchPlayer);
  578. // this.plv.liveSdk.player.on("switchPlayer", () => {
  579. // var switchPosition = plv.mainPosition === 'ppt' ? 'player' : 'ppt';
  580. // switchPlayer(switchPosition);
  581. // });
  582. // this.plv.liveSdk.player.on("switchMainScreen", (main) => {
  583. // console.log("切换主讲位置,当前主屏为", main); // 'player'|'ppt'
  584. // });
  585. // this.plv.liveSdk.player.on("ended", () => {
  586. // this.duraing += this.playTime;
  587. // clearInterval(this.timer);
  588. // this.studyRecord(1);
  589. // });
  590. this.plv.liveSdk.player.on("pause", (state) => {
  591. let duraing = this.playTime - this.duraing;
  592. this.duraing = 0;
  593. this.studyRecord(0, duraing);
  594. clearInterval(this.timer);
  595. });
  596. this.plv.liveSdk.player.on("loadedmetadata", (state) => {
  597. if (this.isFirst) {
  598. this.studyRecord(0);
  599. this.isFirst = false;
  600. }
  601. clearInterval(this.timer);
  602. this.timer = setInterval(() => {
  603. this.studyRecord(0, 20);
  604. this.duraing += 20;
  605. }, 20000);
  606. });
  607. this.plv.liveSdk.player.on("timeupdate", (time) => {
  608. this.playTime = time;
  609. });
  610. }
  611. );
  612. },
  613. studyRecord(status, duraing) {
  614. if (!this.sectionId) {
  615. return;
  616. }
  617. let self = this;
  618. this.$request.studyRecord({
  619. fromPlat: 2, //来源平台 1小程序 2网站
  620. buyCourse: this.buyCourse,
  621. identification: this.identification,
  622. sectionId: parseInt(this.sectionId),
  623. goodsId: parseInt(self.goodsId),
  624. courseId: parseInt(self.courseId),
  625. orderGoodsId: this.orderGoodsId,
  626. studyDuration: parseInt(duraing) || 0,
  627. gradeId: parseInt(self.gradeId),
  628. chapterId: parseInt(self.chapterId),
  629. moduleId: parseInt(self.moduleId),
  630. videoCurrentTime: 2,
  631. status: status,
  632. });
  633. },
  634. /**
  635. * @param {String} 直播js加载
  636. */
  637. loadChatroomScriptzb() {
  638. return new Promise((resolve) => {
  639. if (!window.polyvLivePlayer) {
  640. const myScript = document.createElement("script");
  641. myScript.setAttribute("src", this.chatroomJs);
  642. document.body.appendChild(myScript);
  643. myScript.onload = resolve;
  644. } else {
  645. resolve();
  646. }
  647. });
  648. },
  649. /**
  650. * @param {String} 聊天室js加载
  651. */
  652. loadPlayerScriptzb() {
  653. return new Promise((resolve) => {
  654. if (!window.polyvLivePlayer) {
  655. const myScript = document.createElement("script");
  656. myScript.setAttribute("src", this.playerJs);
  657. document.body.appendChild(myScript);
  658. myScript.onload = resolve;
  659. } else {
  660. resolve();
  661. }
  662. });
  663. },
  664. handleSwitchPlayer() {
  665. var switchPosition = this.plv.mainPosition === "ppt" ? "player" : "ppt";
  666. this.switchPlayer(switchPosition);
  667. },
  668. // 控制栏切换按钮的点击处理函数,仅适用PC端
  669. handleSwitchPlayer() {
  670. var switchPosition = this.plv.mainPosition === "ppt" ? "player" : "ppt";
  671. this.switchPlayer(switchPosition);
  672. },
  673. // 点击到文档tab时调用播放器的resize方法,原因:
  674. // ppt父容器样式改变会导致ppt显示异常,需要调用resize刷新ppt尺寸,该函数用于移动端三分屏场景
  675. handlePptTabClick() {
  676. $("[data-type=ppt]").click(function () {
  677. setTimeout(function () {
  678. this.plv.liveSdk.player.resize();
  679. }, 0);
  680. });
  681. },
  682. // 全屏/退出全屏回调
  683. handleFullscreenChange(isFullScreen, fullScreenElement) {
  684. if (isFullScreen) {
  685. $(fullScreenElement).addClass("plv-watch-pc__top--fullscreen");
  686. } else {
  687. $(fullScreenElement).removeClass("plv-watch-pc__top--fullscreen");
  688. }
  689. },
  690. // 切换主副屏,如需兼容ie,建议通过css的方式去切换位置,dom操作可能导致播放器异常
  691. switchPlayer(nextMainPosition) {
  692. var pcScreens = $(".plv-watch-pc__screen").removeClass(
  693. "plv-watch-pc__screen-main plv-watch-pc__screen-sub"
  694. );
  695. switch (nextMainPosition) {
  696. case "player":
  697. pcScreens.eq(0).addClass("plv-watch-pc__screen-sub");
  698. pcScreens.eq(1).addClass("plv-watch-pc__screen-main");
  699. break;
  700. case "ppt":
  701. pcScreens.eq(0).addClass("plv-watch-pc__screen-main");
  702. pcScreens.eq(1).addClass("plv-watch-pc__screen-sub");
  703. break;
  704. }
  705. this.plv.mainPosition = nextMainPosition;
  706. this.plv.liveSdk.player.resize(); // ppt容器宽高修改,调用resize刷新ppt尺寸
  707. this.plv.liveSdk.player.resizeBarrage(); // 刷新弹幕显示区域尺寸
  708. },
  709. download() {
  710. var url = this.formShare.ercode
  711. var a = document.createElement("a");
  712. var event = new MouseEvent("click");
  713. a.download = "二维码";
  714. a.href = url;
  715. a.dispatchEvent(event);
  716. },
  717. copy() {
  718. var copyInput = document.createElement("input");
  719. //val是要复制的内容
  720. copyInput.setAttribute("value", this.formShare.links);
  721. document.body.appendChild(copyInput);
  722. copyInput.select();
  723. try {
  724. var copyed = document.execCommand("copy");
  725. if (copyed) {
  726. document.body.removeChild(copyInput);
  727. this.$message.success("复制成功");
  728. }
  729. } catch (err) {
  730. this.$message.error("复制失败,请检查浏览器兼容");
  731. }
  732. },
  733. },
  734. };
  735. </script>
  736. <!-- Add "scoped" attribute to limit CSS to this component only -->
  737. <style scoped lang="scss">
  738. .living-room {
  739. background: #eee;
  740. .top-line {
  741. margin: 10px 0;
  742. overflow: hidden;
  743. // padding: 0px 45px;
  744. .title {
  745. font-size: 18px;
  746. float: left;
  747. }
  748. .bottoms {
  749. float: right;
  750. }
  751. .float-right {
  752. width: 100px;
  753. }
  754. }
  755. .living {
  756. position: relative;
  757. width: 900px;
  758. height: 600px;
  759. margin: 0 auto;
  760. #wrap {
  761. position: absolute;
  762. width: 300px;
  763. height: 400px;
  764. left: 600px;
  765. top: 200px;
  766. /deep/ .polyv-cr-head {
  767. background: #ccc;
  768. }
  769. }
  770. #ppt {
  771. position: absolute;
  772. left: 600px;
  773. top: 0;
  774. width: 300px;
  775. height: 200px;
  776. }
  777. #player {
  778. position: absolute;
  779. width: 600px;
  780. height: 600px;
  781. left: 0;
  782. top: 0;
  783. }
  784. .controller {
  785. position: absolute;
  786. width: 600px;
  787. height: 48px;
  788. left: 0;
  789. bottom: 0;
  790. }
  791. }
  792. .sign-modal {
  793. /deep/ .el-dialog__header {
  794. display: none;
  795. }
  796. /deep/ .el-dialog__body {
  797. padding: 0;
  798. overflow: unset;
  799. }
  800. &__content {
  801. .img {
  802. width: 462px;
  803. display: block;
  804. }
  805. .box {
  806. padding: 24px 0;
  807. background: #ffffff;
  808. .title {
  809. font-size: 16px;
  810. font-weight: bold;
  811. color: #333333;
  812. line-height: 24px;
  813. text-align: center;
  814. }
  815. .btn {
  816. display: block;
  817. margin: 40px auto 0;
  818. width: 200px;
  819. height: 40px;
  820. padding: 0;
  821. text-align: center;
  822. line-height: 40px;
  823. border-radius: 8px;
  824. }
  825. }
  826. }
  827. }
  828. .sign-success {
  829. /deep/ .el-dialog__header {
  830. display: none;
  831. }
  832. /deep/ .el-dialog__body {
  833. padding: 0;
  834. overflow: unset;
  835. }
  836. &__content {
  837. width: 400px;
  838. height: 200px;
  839. position: relative;
  840. background: #ffffff;
  841. border-radius: 8px;
  842. .img {
  843. position: absolute;
  844. left: 50%;
  845. top: -54px;
  846. width: 196px;
  847. margin-left: -98px;
  848. display: block;
  849. }
  850. .title {
  851. padding-top: 120px;
  852. font-size: 16px;
  853. font-weight: bold;
  854. color: #333333;
  855. line-height: 24px;
  856. text-align: center;
  857. }
  858. }
  859. }
  860. .popCentent {
  861. display: flex;
  862. flex-direction: column;
  863. align-items: center;
  864. .btns {
  865. width: 300px;
  866. height: 40px;
  867. line-height: 40px;
  868. text-align: center;
  869. background-color: #3577E8;
  870. color: #fff;
  871. font-size: 16px;
  872. border-radius: 20px;
  873. margin-top: 20px;
  874. cursor: pointer;
  875. }
  876. }
  877. .popShare {
  878. .ccopy {
  879. color: #1890ff;
  880. font-size: 14px;
  881. margin-left: 10px;
  882. cursor: pointer;
  883. }
  884. .ercode_pic {
  885. width: 150px;
  886. height: 150px;
  887. // &.bg {
  888. // background: url();
  889. // }
  890. }
  891. }
  892. }
  893. </style>