index.vue 24 KB

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