index.vue 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. <template>
  2. <div
  3. id="videoCy"
  4. :style="{
  5. backgroundImage: `url(${$tools.splitImgHost(goodsData.coverUrl, false)})`
  6. }"
  7. >
  8. <div id="player" v-show="!HideVideo"></div>
  9. <div class="recordStyle" v-if="showRecordStatus">
  10. 您上次看{{
  11. $tools.secondToTime(this.activeSection.videoCurrentTime || 0)
  12. }},正在自动续播
  13. <span class="videoCurrentTime_style">|</span>
  14. <span class="btn_sty" @click="seekVideo0">从头播放</span>
  15. </div>
  16. <takePicture
  17. ref="takePicture"
  18. @returnParameter="returnParameter"
  19. ></takePicture>
  20. <count-down ref="countDown" @againSubmit="postStudyRecord(1)"></count-down>
  21. </div>
  22. </template>
  23. <script>
  24. import takePicture from "@/components/takePicture/index.vue";
  25. import countDown from "@/components/countDown/index.vue";
  26. export default {
  27. components: { takePicture, countDown },
  28. inject: ["getGoodsData"],
  29. props: {
  30. activeSection: {
  31. type: Object,
  32. default: () => {
  33. return {};
  34. } //当前节数据
  35. }
  36. },
  37. data() {
  38. return {
  39. vodPlayerJs: "https://player.polyv.net/script/player.js",
  40. player: null,
  41. HideVideo: false, //是否隐藏播放器
  42. photoList: [], //抓拍时间拍照数组
  43. photoHistoryList: [], //历史和已拍照数据
  44. photoIndex: 0, //当前拍照对应索引
  45. showRecordStatus: false, //是否显示从头播放提示
  46. showRecordSetTimeOut: null, //从头播放提示计时器函数
  47. openPhotoStatus: 0, //暂存学习状态
  48. commitTime: null, //暂存时间-节流
  49. commitTimePhoto: null, //判断拍照时刻-节流
  50. videoPauseSetTimeout: null, //定时器停留太久触发
  51. failToRegister: false, //报名推送不通过
  52. videoPauseSetTimeStatus: false
  53. };
  54. },
  55. computed: {
  56. goodsData() {
  57. return this.getGoodsData();
  58. }
  59. },
  60. watch: {
  61. //因为刚开始获取不到goodsData的数据 所以需要监听
  62. goodsData: function(newVal, oldVal) {
  63. if (newVal) {
  64. this.getBeforeWork(); //处理前置任务
  65. }
  66. }
  67. },
  68. created() {
  69. if (!window.polyvPlayer) {
  70. const myScript = document.createElement("script");
  71. myScript.setAttribute("src", this.vodPlayerJs);
  72. myScript.onload = () => {
  73. console.log("加载成功");
  74. };
  75. document.body.appendChild(myScript);
  76. }
  77. },
  78. mounted() {
  79. this.$bus.$on("toPlay", async item => {
  80. if (this.player) {
  81. this.player.destroy(); //初始化播放器
  82. }
  83. this.initData(); //初始化参数
  84. await this.getRecordHistoryPhoto(); //获取拍照历史记录
  85. await this.getRecordLast(); //获取播放记录
  86. await this.loadPlayer(); //加载播放内容
  87. this.player.on("s2j_onPlayerInitOver", () => {
  88. this.player.on("s2j_onPlayStart", this.onPlayStatus); //视频初次播放时触发
  89. this.player.on("s2j_onVideoPause", this.onVideoPause); //视频暂停时触发
  90. this.player.on("s2j_onVideoPlay", this.onVideoPlay); //视频初次播放或由暂停恢复播放时触发
  91. this.player.on("s2j_onPlayOver", this.onPlayOver); //当前视频播放完毕时触发
  92. this.player.on("s2j_onPlayerError", this.onPlayerError); //播放出现错误时触发
  93. this.player.on("serverError", this.serverError); //发生业务逻辑错误时触发,比如授权验证失败、域名黑白名单验证不通过等错误。参数返回事件名称和错误代码。
  94. }); //播放器初始化完毕时触发。播放器提供的方法需要在此事件发生后才可以调用。
  95. });
  96. // document.addEventListener("visibilitychange", this.pauseVideo);
  97. },
  98. methods: {
  99. getBeforeWork() {},
  100. //初始化参数
  101. initData() {
  102. this.commitTime = null;
  103. this.commitTimePhoto = null;
  104. this.openPhotoStatus = 0;
  105. this.videoPauseSetTimeStatus = false;
  106. clearTimeout(this.videoPauseSetTimeout); //删除暂停计算拍照定时器
  107. },
  108. //获取播放记录
  109. getRecordLast() {
  110. return new Promise(resolve => {
  111. clearTimeout(this.showRecordSetTimeOut);
  112. let data = {
  113. orderGoodsId: this.goodsData.orderGoodsId,
  114. gradeId: this.goodsData.gradeId,
  115. goodsId: this.goodsData.goodsId,
  116. courseId: this.activeSection.courseId,
  117. moduleId: this.activeSection.moduleId,
  118. chapterId: this.activeSection.chapterId,
  119. sectionId: this.activeSection.sectionId
  120. };
  121. this.$request.recordLast(data).then(res => {
  122. if (
  123. res.data &&
  124. res.data.videoCurrentTime &&
  125. res.data.videoCurrentTime - 3 >= 0
  126. ) {
  127. this.activeSection.videoCurrentTime = res.data.videoCurrentTime - 3;
  128. }
  129. resolve();
  130. });
  131. });
  132. },
  133. //从头播放
  134. seekVideo0() {
  135. this.player.j2s_seekVideo(0);
  136. this.showRecordStatus = false;
  137. },
  138. //获取拍照历史记录
  139. getRecordHistoryPhoto() {
  140. return new Promise(resolve => {
  141. var data = {
  142. sectionId: this.activeSection.sectionId,
  143. goodsId: this.goodsData.goodsId,
  144. courseId: this.activeSection.courseId,
  145. gradeId: this.goodsData.gradeId,
  146. orderGoodsId: this.goodsData.orderGoodsId,
  147. chapterId: this.activeSection.chapterId,
  148. moduleId: this.activeSection.moduleId
  149. };
  150. this.$request.getPhotoLastRecord(data).then(res => {
  151. //清空历史数据
  152. this.photoList = [];
  153. this.photoHistoryList = [];
  154. this.photoIndex = 0;
  155. for (let i = 0; i < res.data.length; i++) {
  156. //-2存储随机拍照数组
  157. if (res.data[i].photoIndex == -2 && res.data[i].timeInterval) {
  158. this.photoList = res.data[i].timeInterval.split(",");
  159. } else {
  160. this.photoHistoryList.push(res.data[i].photoIndex);
  161. }
  162. }
  163. resolve();
  164. });
  165. });
  166. },
  167. //计算拍照逻辑
  168. photoLogic() {
  169. if (this.photoList.length > 0 || this.activeSection.learning == 1) return; //已从历史拍照数据获得
  170. var polyvPlayerContext = this.player;
  171. let totalVideoTime = polyvPlayerContext.j2s_getDuration();
  172. let duration = polyvPlayerContext.j2s_getCurrentTime();
  173. if (this.goodsData.erJianErZao) {
  174. this.photoList = this.randomConfig(totalVideoTime, duration);
  175. } else if (this.goodsData.jjShiGongYuan && this.goodsData.orderYears) {
  176. this.photoList = this.ShiPhotoList(totalVideoTime, duration);
  177. } else if (this.goodsData.goodsPhotographConfig.photoNum > 0) {
  178. this.photoList = this.getPhotoList(
  179. totalVideoTime,
  180. this.goodsData.goodsPhotographConfig.photoNum
  181. );
  182. }
  183. //兼容已有观看历史
  184. for (let i = 0; i < this.photoList.length - 1; i++) {
  185. if (this.photoList[i] < duration && this.photoList[i + 1] > duration) {
  186. this.photoIndex = i + 1;
  187. break;
  188. }
  189. if (duration > this.photoList[this.photoList.length - 1]) {
  190. this.photoIndex = this.photoList.length - 1; //取最后一个下标
  191. break;
  192. }
  193. }
  194. },
  195. //普通拍照
  196. getPhotoList(totalVideoTime, photoNum) {
  197. let photoList = [];
  198. if (totalVideoTime >= 900) {
  199. //大于15分钟
  200. if (photoNum == 1) {
  201. //开头拍1张
  202. photoList.push(1);
  203. } else if (photoNum == 3) {
  204. //拍3张
  205. photoList.push(0); //开头拍一张
  206. let centerTime = Math.floor(totalVideoTime / 2); //获取中间时间
  207. let centerMinTime = centerTime - 300; //前后5分钟
  208. let centerMaxTime = centerTime + 300;
  209. let centerTakeTime = this.randomNum(centerMinTime, centerMaxTime);
  210. photoList.push(centerTakeTime); //中间拍一张
  211. let endMaxTime = totalVideoTime - 60;
  212. let endMinTime = totalVideoTime - 300;
  213. let endTakeTime = this.randomNum(endMinTime, endMaxTime);
  214. photoList.push(endTakeTime); //最后拍一张
  215. }
  216. } else {
  217. //小于15分钟,只拍前后各一张
  218. if (photoNum == 1) {
  219. //开头拍1张
  220. photoList.push(1);
  221. } else if (photoNum == 3) {
  222. photoList.push(1);
  223. let centerTime = this.randomNum(
  224. (1 / 3) * totalVideoTime,
  225. (2 / 3) * totalVideoTime
  226. );
  227. photoList.push(centerTime);
  228. let endTakeTime = this.randomNum(
  229. (2 / 3) * totalVideoTime,
  230. totalVideoTime
  231. );
  232. photoList.push(endTakeTime);
  233. }
  234. }
  235. this.postCoursePhotoRecord(true); //提交随机拍照时间数组
  236. return photoList;
  237. },
  238. //施工继教
  239. ShiPhotoList(totalVideoTime) {
  240. //施工继教带年份的订单拍照设置
  241. let time1 = 50 * 60; //拍照间隔多久一张 50分钟
  242. let num = Math.trunc(totalVideoTime / time1) + 1; //拍照数量
  243. let photoList = [];
  244. for (let i = 0; i < num; i++) {
  245. photoList.push(i * time1);
  246. }
  247. return photoList;
  248. },
  249. // 随机拍摄时间(二建)
  250. randomConfig(totalVideoTime, duration) {
  251. this.photoHistoryList = [];
  252. let photoList = [duration];
  253. let pre = duration;
  254. if (totalVideoTime > 300) {
  255. while (pre <= totalVideoTime) {
  256. pre += this.randomNum(780, 900);
  257. pre <= totalVideoTime && photoList.push(pre);
  258. }
  259. if (totalVideoTime - 300 > photoList.slice(-1)[0]) {
  260. photoList.push(this.randomNum(totalVideoTime - 180, totalVideoTime));
  261. }
  262. }
  263. return photoList;
  264. },
  265. //postTime = true 只提交随机时间 false 提交拍照
  266. postCoursePhotoRecord(postTime = false, photoUrl) {
  267. return new Promise((resolve, reject) => {
  268. let currentTime = this.player.j2s_getCurrentTime();
  269. let data = {
  270. goodsId: this.goodsData.goodsId,
  271. gradeId: this.goodsData.gradeId,
  272. orderGoodsId: this.goodsData.orderGoodsId,
  273. courseId: this.activeSection.courseId,
  274. moduleId: this.activeSection.moduleId,
  275. chapterId: this.activeSection.chapterId,
  276. sectionId: this.activeSection.sectionId,
  277. photo: postTime ? "" : photoUrl,
  278. photoTime: parseInt(currentTime > 0 ? currentTime : 0),
  279. photoIndex: postTime ? -2 : parseInt(this.photoIndex), //从0算起,-2只提交随机时间
  280. photoNum: parseInt(this.goodsData.goodsPhotographConfig.photoNum),
  281. timeInterval: postTime ? this.photoList.join(",") : ""
  282. };
  283. this.$request
  284. .coursePhotoRecord(data)
  285. .then(res => {
  286. resolve(res);
  287. })
  288. .catch(err => {
  289. reject();
  290. });
  291. });
  292. },
  293. //随机拍摄时间
  294. randomNum(minNum, maxNum) {
  295. switch (arguments.length) {
  296. case 1:
  297. return parseInt(Math.random() * minNum + 1, 10);
  298. break;
  299. case 2:
  300. return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
  301. break;
  302. default:
  303. return 0;
  304. break;
  305. }
  306. },
  307. // 播放视频
  308. loadPlayer() {
  309. return new Promise(resolve => {
  310. var self = this;
  311. const polyvPlayer = window.polyvPlayer;
  312. self.$request
  313. .obtainpolyvvideosign(self.activeSection.recordingUrl)
  314. .then(res => {
  315. const autoPlay = self.goodsData.goodsPlayConfig
  316. ? self.goodsData.goodsPlayConfig.autoPlay
  317. : true;
  318. const isAllowSeek = self.goodsData.goodsPlayConfig
  319. ? self.goodsData.goodsPlayConfig.isAllowSeek
  320. : "on";
  321. const playbackRate = self.goodsData.goodsPlayConfig
  322. ? self.goodsData.goodsPlayConfig.playbackRate
  323. : false;
  324. self.player = polyvPlayer({
  325. wrap: "#player",
  326. width: 810,
  327. height: 455,
  328. preventKeyboardEvent: true, //是否屏蔽键盘事件,为true时屏蔽。
  329. showLine: true, //是否显示线路选择按钮
  330. ban_history_time: "on", //是否禁用续播功能,取值:{on,off}。
  331. vid: self.activeSection.recordingUrl,
  332. autoplay: autoPlay, // 是否自动播放。
  333. ban_seek: isAllowSeek, //是否禁止拖拽进度条,取值:{on,off}。
  334. speed: playbackRate, //当speed参数值为boolean类型时,代表是否显示倍速切换的按钮。
  335. teaser_show: 1, //是否播放片头:0 不播放,1 播放。片头可在管理后台进行设置。
  336. tail_show: 1, //是否播放片尾:0 不播放,1 播放。片尾可在管理后台进行设置。
  337. hideSwitchPlayer: true, //是否隐藏H5和Flash播放器的切换按钮。
  338. watchStartTime: self.activeSection.videoCurrentTime || 0, // 播放开始时间,表示视频从第几秒开始播放,参数值需小于视频时长。
  339. ts: res.data.ts, //移动播放加密视频需传入的时间戳。
  340. sign: res.data.sign, //移动端播放加密视频所需的签名。
  341. playsafe: function(vid, next) {
  342. self.$request.obtainpolyvvideopcsign(vid).then(res => {
  343. next(res.data);
  344. });
  345. } //PC端播放加密视频所需的授权凭证。
  346. });
  347. self.$emit("videoScript", this.player); //抛出播放实例
  348. resolve();
  349. });
  350. });
  351. },
  352. //监听器
  353. timeEvent() {
  354. // 定时提交学习记录
  355. this.submitStudyRecords();
  356. //拍照监听执行
  357. let time = new Date().getTime();
  358. if (time >= this.commitTimePhoto) {
  359. this.watchPhoto();
  360. this.commitTimePhoto = time + 1000;
  361. }
  362. },
  363. //拍照监听执行
  364. watchPhoto() {
  365. if (
  366. this.photoList.length == 0 ||
  367. this.activeSection.learning == 1 ||
  368. this.$refs.takePicture.takePhotoModal ||
  369. this.failToRegister
  370. )
  371. return;
  372. let videoTime = this.player.j2s_getCurrentTime();
  373. let photoTime = 0; //获取拍照秒数
  374. for (let i = 0; i < this.photoList.length; i++) {
  375. photoTime = Number(this.photoList[i]); //获取拍照秒数
  376. if (photoTime < videoTime && photoTime > videoTime - 8) {
  377. //3秒区间内才触发拍照,避免拉动滚动条
  378. if (
  379. this.photoHistoryList.indexOf(i) < 0 &&
  380. this.activeSection.learning != 1
  381. ) {
  382. //不存在拍照历史,没有重修过,没有学过,则拍照
  383. this.player.j2s_pauseVideo(); //暂停
  384. this.photoIndex = i;
  385. this.openPhoto(); //启动拍照
  386. }
  387. }
  388. }
  389. },
  390. // 定时提交学习记录
  391. submitStudyRecords() {
  392. let time = new Date().getTime();
  393. if (time >= this.commitTime) {
  394. this.postStudyRecord(0);
  395. this.commitTime = time + 15000;
  396. }
  397. },
  398. //视频初次播放时触发
  399. onPlayStatus() {
  400. //计算拍照逻辑
  401. this.photoLogic();
  402. //开启上次播放位置提示
  403. if (this.activeSection.videoCurrentTime) {
  404. this.showRecordStatus = true;
  405. this.showRecordSetTimeOut = setTimeout(() => {
  406. this.showRecordStatus = false;
  407. }, 5000);
  408. }
  409. this.player.HTML5.video.addEventListener("timeupdate", this.timeEvent); //监听器
  410. console.log("视频初次播放时触发", this.player.j2s_getCurrentTime());
  411. },
  412. //视频暂停时触发
  413. onVideoPause() {
  414. if (
  415. this.activeSection.learning != 1 &&
  416. this.goodsData.erJianErZao &&
  417. !this.failToRegister
  418. ) {
  419. this.videoPauseSetTimeout = setTimeout(() => {
  420. if (this.isFullScreen()) {
  421. this.exitFullscreen();
  422. }
  423. this.videoPauseSetTimeStatus = true;
  424. this.$confirm(
  425. "检测播放暂停或拍照停留时间过长,刷新当前页面",
  426. "提示",
  427. {
  428. confirmButtonText: "确定",
  429. cancelButtonText: "取消",
  430. showCancelButton: false,
  431. closeOnClickModal: false,
  432. closeOnPressEscape: false,
  433. showClose: false,
  434. type: "warning"
  435. }
  436. )
  437. .then(() => {
  438. this.$router.go(0);
  439. })
  440. .catch(() => {});
  441. }, 300000); //300000
  442. }
  443. },
  444. //视频恢复播放时触发
  445. onVideoPlay() {
  446. if (
  447. this.activeSection.learning != 1 &&
  448. this.goodsData.erJianErZao &&
  449. !this.failToRegister
  450. ) {
  451. clearTimeout(this.videoPauseSetTimeout);
  452. }
  453. console.log("视频恢复播放时触发");
  454. },
  455. //当前视频播放完毕时触发
  456. onPlayOver() {
  457. this.$message({
  458. type: "success",
  459. message: "播放完毕"
  460. });
  461. this.isFullScreen();
  462. clearTimeout(this.videoPauseSetTimeout); //删除暂停计算拍照定时器
  463. this.postStudyRecord(1);
  464. console.log("当前视频播放完毕时触发");
  465. },
  466. //判断是全屏则退出全屏
  467. isFullScreen() {
  468. if (!!(document.webkitIsFullScreen || this.fullele())) {
  469. try {
  470. var de = document;
  471. if (de.exitFullscreen) {
  472. de.exitFullscreen();
  473. } else if (de.mozCancelFullScreen) {
  474. de.mozCancelFullScreen();
  475. } else if (de.webkitCancelFullScreen) {
  476. de.webkitCancelFullScreen();
  477. }
  478. } catch (err) {}
  479. }
  480. },
  481. fullele() {
  482. return (
  483. document.fullscreenElement ||
  484. document.webkitFullscreenElement ||
  485. document.msFullscreenElement ||
  486. document.mozFullScreenElement ||
  487. null
  488. );
  489. },
  490. //播放出现错误时触发
  491. onPlayerError() {
  492. this.$message.error("播放出现错误时触发");
  493. },
  494. //发生业务逻辑错误
  495. serverError() {
  496. this.$message.error("发生业务逻辑错误");
  497. },
  498. //启动拍照
  499. openPhoto() {
  500. if (this.isFullScreen()) {
  501. this.exitFullscreen();
  502. }
  503. this.$refs.takePicture.openPhoto();
  504. this.HideVideo = true;
  505. },
  506. //拍照成功回显 url
  507. async returnParameter(url) {
  508. this.HideVideo = false;
  509. let compareFaceData = await this.faceRecognition(url);
  510. if (compareFaceData >= 80) {
  511. let file = this.$tools.convertBase64UrlToBlob(url);
  512. const photoUrl = await this.$upload.upload(file, 0, {
  513. gradeId: this.goodsData.gradeId,
  514. orderGoodsId: this.goodsData.orderGoodsId
  515. });
  516. this.postCoursePhotoRecord(false, photoUrl)
  517. .then(async res => {
  518. this.photoHistoryList.push(this.photoIndex);
  519. const STATUS = await this.postStudyRecord(
  520. 0,
  521. photoUrl,
  522. compareFaceData
  523. ); //提交记录
  524. //恢复播放
  525. if (STATUS) {
  526. var polyvPlayerContext = this.player;
  527. if (polyvPlayerContext && this.openPhotoStatus !== 1) {
  528. polyvPlayerContext.j2s_resumeVideo();
  529. }
  530. }
  531. })
  532. .catch(err => {
  533. this.$message({
  534. type: "warning",
  535. message: "上传接口报错,请重新拍照上传"
  536. });
  537. setTimeout(() => {
  538. this.openPhoto();
  539. }, 1500);
  540. });
  541. } else {
  542. this.$message({
  543. type: "warning",
  544. message: "人脸匹配不通过,请重新拍照上传"
  545. });
  546. setTimeout(() => {
  547. this.openPhoto();
  548. }, 1500);
  549. }
  550. },
  551. /**
  552. * 提交观看记录
  553. * status 1 学完 0未学完
  554. */
  555. postStudyRecord(status = 0, imgUrl, compareFaceData) {
  556. return new Promise((resolve, reject) => {
  557. let currentTime = 0;
  558. let PlayDuration = 0;
  559. var polyvPlayerContext = this.player;
  560. if (polyvPlayerContext) {
  561. currentTime = polyvPlayerContext.j2s_getCurrentTime(); //当前视频播放时刻
  562. PlayDuration = polyvPlayerContext.j2s_realPlayVideoTime(); //本次看的时长
  563. }
  564. let data = {
  565. orderGoodsId: parseInt(this.goodsData.orderGoodsId),
  566. goodsId: parseInt(this.goodsData.goodsId),
  567. gradeId: parseInt(this.goodsData.gradeId),
  568. courseId: this.activeSection.courseId,
  569. moduleId: this.activeSection.moduleId,
  570. chapterId: this.activeSection.chapterId,
  571. sectionId: this.activeSection.sectionId,
  572. fromPlat: 2, //来源平台 1小程序 2网站
  573. photo: imgUrl || "",
  574. studyDuration: parseInt(PlayDuration > 0 ? PlayDuration : 0),
  575. videoCurrentTime: parseInt(currentTime > 0 ? currentTime : 0),
  576. erJianErZao: this.goodsData.erJianErZao
  577. };
  578. if (imgUrl) {
  579. data.similarity = compareFaceData; // 相似度
  580. }
  581. if (status > 0) {
  582. data.status = status;
  583. }
  584. // /study/record 学习记录
  585. this.$request
  586. .studyRecord(data)
  587. .then(res => {
  588. if (status > 0) {
  589. this.openPhotoStatus = 0;
  590. this.$message.success("学习完成");
  591. this.$bus.$emit("BackVideoFunc", this.activeSection);
  592. resolve(false);
  593. }
  594. if (this.openPhotoStatus === 1) {
  595. this.postStudyRecord(1);
  596. }
  597. if (status == 0 && this.openPhotoStatus !== 1) {
  598. resolve(true);
  599. }
  600. })
  601. .catch(err => {
  602. if (err.code === 600) {
  603. polyvPlayerContext.j2s_pauseVideo();
  604. this.failToRegister = true; //报名推送不通过
  605. this.$confirm(`开通信息推送不成功,无法学习!`, "提示", {
  606. confirmButtonText: "确定",
  607. closeOnClickModal: false,
  608. closeOnPressEscape: false,
  609. distinguishCancelAndClose: false,
  610. showCancelButton: false,
  611. showClose: false
  612. })
  613. .then(_ => {
  614. //停止执行-退出页面
  615. this.$router.back(-1);
  616. })
  617. .catch(_ => {
  618. //停止执行-退出页面
  619. this.$router.back(-1);
  620. });
  621. } else if (err.code === 559) {
  622. console.log("拍照不够触发");
  623. this.$message.error(err.msg);
  624. this.openPhotoStatus = 1;
  625. setTimeout(() => {
  626. this.openPhoto();
  627. }, 1500);
  628. } else if (err.code === 558) {
  629. this.$refs.countDown.openBoxs(parseInt(err.msg.split(",")[1]));
  630. } else {
  631. this.$message.error(err.msg || "未知错误");
  632. }
  633. });
  634. });
  635. },
  636. //人脸校验
  637. faceRecognition(url) {
  638. return new Promise(resolve => {
  639. this.$request
  640. .faceCertificationCompareFace({
  641. imageA: url,
  642. orderGoodsId: this.goodsData.orderGoodsId,
  643. gradeId: this.goodsData.gradeId
  644. })
  645. .then(res => {
  646. resolve(res.data);
  647. })
  648. .catch(err => {
  649. if (err.toString().indexOf("timeout") != -1) {
  650. err = {
  651. msg: "拍照超时,请重新拍照"
  652. };
  653. }
  654. this.$message({
  655. type: "warning",
  656. message: err.msg
  657. });
  658. setTimeout(() => {
  659. this.openPhoto();
  660. }, 1500);
  661. });
  662. });
  663. },
  664. //页面显示隐藏逻辑
  665. pauseVideo() {
  666. if (
  667. this.$refs.takePicture.takePhotoModal ||
  668. this.$refs.takePicture.photoBadStatus ||
  669. this.failToRegister ||
  670. this.videoPauseSetTimeStatus
  671. ) {
  672. return;
  673. }
  674. let _p = this.player;
  675. if (document.visibilityState === "hidden") {
  676. _p && _p.j2s_pauseVideo();
  677. } else if (
  678. _p &&
  679. parseInt(_p.j2s_getCurrentTime()) < _p.j2s_getDuration()
  680. ) {
  681. this.player.j2s_resumeVideo();
  682. }
  683. }
  684. },
  685. beforeDestroy() {
  686. this.$bus.$off("toPlay");
  687. clearTimeout(this.videoPauseSetTimeout); //删除暂停计算拍照定时器
  688. // document.removeEventListener("visibilitychange", this.pauseVideo);
  689. this.player && this.player.destroy(); //初始化播放器
  690. this.player &&
  691. this.player.HTML5.video.removeEventListener("timeupdate", this.timeEvent); //监听器
  692. this.$msgbox.close();
  693. }
  694. };
  695. </script>
  696. <style lang="scss" scoped>
  697. #videoCy {
  698. width: 100%;
  699. height: 100%;
  700. background: url() no-repeat center center;
  701. background-size: contain;
  702. position: relative;
  703. }
  704. .recordStyle {
  705. position: absolute;
  706. bottom: 60px;
  707. padding: 6px 12px;
  708. left: 8px;
  709. background-color: rgba(0, 0, 0, 0.4);
  710. color: #fff;
  711. border-radius: 24px;
  712. user-select: none;
  713. .videoCurrentTime_style {
  714. display: inline-block;
  715. width: 50px;
  716. text-align: center;
  717. }
  718. .btn_sty {
  719. cursor: pointer;
  720. }
  721. }
  722. </style>