single_con_detail.html 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. <!-- +---------------------------------------------------------------------- -->
  2. <!-- | CRMEB [ CRMEB赋能开发者,助力企业发展 ] -->
  3. <!-- +---------------------------------------------------------------------- -->
  4. <!-- | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved. -->
  5. <!-- +---------------------------------------------------------------------- -->
  6. <!-- | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权 -->
  7. <!-- +---------------------------------------------------------------------- -->
  8. <!-- | Author: CRMEB Team <admin@crmeb.com> -->
  9. <!-- +---------------------------------------------------------------------- -->
  10. {extend name="public/container"}
  11. {block name="title"}专题详情{/block}
  12. {block name="aliplayer"}
  13. <link rel="stylesheet" href="//g.alicdn.com/de/prismplayer/2.9.23/skins/default/aliplayer-min.css">
  14. <script src="//g.alicdn.com/de/prismplayer/2.9.23/aliplayer-min.js"></script>
  15. <script src="//g.alicdn.com/de/prismplayer/2.9.23/hls/aliplayer-hls-min.js"></script>
  16. {/block}
  17. {block name="head"}
  18. <style>
  19. .prism-player .prism-info-display {
  20. box-sizing: border-box;
  21. }
  22. .prism-player .prism-big-play-btn {
  23. bottom: 50% !important;
  24. left: 50% !important;
  25. transform: translate(-50%, 50%);
  26. }
  27. .audio-player {
  28. display: flex;
  29. flex-direction: column;
  30. justify-content: center;
  31. }
  32. .audio-player .image img {
  33. display: block;
  34. width: 4.64rem;
  35. margin: 0 auto;
  36. }
  37. .audio-player .control {
  38. display: flex;
  39. align-items: center;
  40. padding: .4rem .3rem 0;
  41. }
  42. .audio-player .icon {
  43. font-size: .64rem;
  44. color: #191C6E;
  45. }
  46. .audio-player .timeline {
  47. flex: 1;
  48. display: flex;
  49. align-items: center;
  50. margin-left: .3rem;
  51. font-size: .28rem;
  52. color: #191C6E;
  53. }
  54. .audio-player .progress {
  55. flex: 1;
  56. height: .04rem;
  57. border-radius: .02rem;
  58. margin: 0 .18rem;
  59. background-color: rgba(44, 142, 255, 0.2);
  60. }
  61. .audio-player .inner {
  62. position: relative;
  63. width: 0;
  64. height: .04rem;
  65. border-radius: .02rem;
  66. background-color: #191C6E;
  67. }
  68. .audio-player .thumb {
  69. position: absolute;
  70. top: 50%;
  71. right: 0;
  72. width: .16rem;
  73. height: .16rem;
  74. border-radius: 50%;
  75. background-color: #191C6E;
  76. transform: translate(50%, -50%);
  77. }
  78. .title {
  79. padding: .3rem;
  80. background-color: #FFFFFF;
  81. font-size: .36rem;
  82. color: #333333;
  83. }
  84. .detail {
  85. padding: .3rem;
  86. border-top: .14rem solid #F5F5F5;
  87. }
  88. .detail img {
  89. display: block;
  90. width: 100%;
  91. }
  92. .cover {
  93. display: block;
  94. width: 100%;
  95. }
  96. </style>
  97. {/block}
  98. {block name="content"}
  99. <div v-cloak id="app">
  100. <div :hidden="singleContent.light_type === 2" id="J_prismPlayer"></div>
  101. <img v-if="singleContent.light_type === 3 && !singleProfile.videoId && !singleProfile.link" :src="singleContent.image" class="cover" :style="{ height: height + 'px' }">
  102. <div v-if="singleContent.light_type === 2" :style="{ height: height + 'px' }" class="audio-player">
  103. <div class="image">
  104. <img :src="isPause ? '{__WAP_PATH}zsff/images/audio1.png' : '{__WAP_PATH}zsff/images/audio2.gif'" alt="">
  105. </div>
  106. <div v-if="!(!singleProfile.videoId && !singleProfile.link)" class="control">
  107. <button @click="toggleTask">
  108. <svg class="icon" aria-hidden="true">
  109. <use :xlink:href="isPause ? '#iconbofang1' : '#iconzanting'"></use>
  110. </svg>
  111. </button>
  112. <div class="timeline">
  113. <div>{{ currentTime | formatTime(duration) }}</div>
  114. <div class="progress">
  115. <div :style="{ width: taskRange + '%' }" class="inner">
  116. <div class="thumb" @touchmove="moveTask" @touchend="moveEndTask"></div>
  117. </div>
  118. </div>
  119. <div>{{ duration | formatTime }}</div>
  120. </div>
  121. </div>
  122. </div>
  123. <div class="title">{{ singleContent.title }}</div>
  124. <div class="detail" v-html="singleContent.abstract"></div>
  125. <pay-dialog :open.sync="payDialogOpen" :money="singleContent.money" :now_money="now_money" :special_id="id" :pay_type_num="2" :is-wechat="isWechat" :is-alipay="is_alipay"
  126. :is-balance="is_yue" :template-id="templateIds" :wxpay-h5="wxpayH5" :is-member="singleContent.is_member" :member-money="singleContent.member_money"
  127. :member-link="memberLink" @change="changeVal"></pay-dialog>
  128. </div>
  129. {/block}
  130. {block name="foot"}
  131. <script>
  132. require([
  133. 'vue',
  134. 'helper',
  135. 'store',
  136. 'moment',
  137. 'components/pay-dialog/index',
  138. ], function (
  139. Vue,
  140. $h,
  141. store,
  142. moment,
  143. PayDialog
  144. ) {
  145. // var try = {$try};
  146. var id = {$id};
  147. var now_money = {$now_money};
  148. var isWechat = {$isWechat? 'true': 'false'};
  149. var is_alipay = {$is_alipay? 'true': 'false'};
  150. var is_yue = {$is_yue? 'true': 'false'};
  151. var wxpayH5 = {$is_h5_wechat_payment_switch? 'true': 'false'};
  152. var memberLink = "{:url('special/member_recharge')}";
  153. new Vue({
  154. el: '#app',
  155. filters: {
  156. formatTime: function (time, sibling) {
  157. var duration = moment.duration(time * 1000);
  158. var hours = duration.hours();
  159. var siblingHours = sibling ? moment.duration(sibling * 1000).hours() : 0;
  160. return moment({
  161. h: hours,
  162. m: duration.minutes(),
  163. s: duration.seconds()
  164. }).format((hours || siblingHours ? 'HH:' : '') + 'mm:ss');
  165. }
  166. },
  167. components: {
  168. 'pay-dialog': PayDialog
  169. },
  170. data: {
  171. id: id,
  172. now_money: now_money,
  173. height: Math.floor(window.innerWidth * 9 / 16),
  174. singleContent: {},
  175. singleProfile: {},
  176. isPause: true,
  177. currentTime: 0,
  178. duration: 0,
  179. payDialogOpen: false,
  180. pay_type_num: -1,
  181. isWechat: isWechat,
  182. is_alipay: is_alipay,
  183. is_yue: is_yue,
  184. wxpayH5: wxpayH5,
  185. memberLink: memberLink,
  186. templateIds: '',
  187. PlayAuth: ''
  188. },
  189. watch: {
  190. isPause: function (value) {
  191. value ? this.player.pause() : this.player.play();
  192. }
  193. },
  194. computed: {
  195. taskRange: function () {
  196. return Math.floor(this.currentTime / this.duration * 100);
  197. }
  198. },
  199. created: function () {
  200. this.getSingleContent();
  201. },
  202. methods: {
  203. getSingleContent: function () {
  204. var vm = this;
  205. store.baseGet($h.U({
  206. c: 'special',
  207. a: 'single_con_content',
  208. q: {id: id}
  209. }), function (res) {
  210. vm.singleContent = res.data.data;
  211. vm.singleProfile = res.data.data.singleProfile;
  212. console.log(vm.singleContent);
  213. console.log(vm.singleProfile);
  214. if (vm.singleProfile.videoId) {
  215. vm.getPlayAuth();
  216. } else if (vm.singleProfile.link) {
  217. vm.createPlayer();
  218. }
  219. });
  220. },
  221. // 获取playauth
  222. getPlayAuth: function () {
  223. var vm = this;
  224. $h.loadFFF();
  225. store.baseGet($h.U({
  226. c: 'special',
  227. a: 'get_video_playback_credentials',
  228. q: {
  229. type: 2,
  230. videoId: this.singleProfile.videoId
  231. }
  232. }), function (res) {
  233. var request = new XMLHttpRequest();
  234. $h.loadClear();
  235. request.onreadystatechange = function () {
  236. if (request.readyState === 4) {
  237. try {
  238. var data = JSON.parse(request.responseText);
  239. if (request.status === 200) {
  240. vm.PlayAuth = data.PlayAuth;
  241. vm.duration = data.VideoMeta.Duration;
  242. vm.createPlayer();
  243. } else {
  244. layer.msg(data.Message);
  245. }
  246. } catch (error) {
  247. layer.msg(error);
  248. }
  249. }
  250. };
  251. request.open('GET', res.data.msg);
  252. request.send();
  253. }, function () {
  254. $h.loadClear();
  255. });
  256. },
  257. createPlayer: function () {
  258. this.player = new Aliplayer({
  259. id: 'J_prismPlayer',
  260. height: this.height + 'px',
  261. source: this.singleProfile.link,
  262. vid: this.singleProfile.videoId,
  263. playauth: this.PlayAuth,
  264. cover: this.singleContent.image,
  265. format: this.singleContent.light_type == 2 ? 'mp3' : '',
  266. autoplay: false,
  267. controlBarVisibility: 'click',
  268. showBarTime: 3e3
  269. });
  270. this.player.on('ready', this.handleReady);
  271. this.player.on('pause', this.handlePause);
  272. this.player.on('canplay', this.handleCanplay);
  273. this.player.on('ended', this.handleEnded);
  274. this.player.on('timeupdate', this.handleTimeupdate);
  275. },
  276. handleReady: function () {
  277. if (this.singleProfile.link) {
  278. this.duration = this.player.getDuration();
  279. }
  280. },
  281. handlePause: function () {
  282. if (!this.isPause) {
  283. this.isPause = true;
  284. }
  285. },
  286. handleCanplay: function () {
  287. if (this.singleContent.isPay) {
  288. if (!this.seeked) {
  289. this.seeked = true;
  290. this.player.seek(this.singleContent.viewing_time / 1000);
  291. }
  292. } else {
  293. this.player.setPreviewTime(this.singleProfile.try_time * 60);
  294. }
  295. },
  296. handleEnded: function () {
  297. var vm = this;
  298. if (!this.singleContent.isPay) {
  299. layer.confirm('购买后可' + (this.singleContent.light_type === 2 ? '听' : '看') + '全部内容,是否购买?', {
  300. title: false,
  301. closeBtn: false,
  302. btn: ['购买', '取消']
  303. }, function (index) {
  304. vm.payDialogOpen = true;
  305. layer.close(index);
  306. });
  307. }
  308. },
  309. handleTimeupdate: function () {
  310. this.currentTime = this.player.getCurrentTime();
  311. if (!this.singleContent.isPay) {
  312. return;
  313. }
  314. var floorTime = Math.floor(this.currentTime);
  315. if (floorTime && floorTime !== this.floorTime && !(floorTime % 10)) {
  316. this.floorTime = floorTime;
  317. this.setViewing();
  318. }
  319. },
  320. setViewing: function () {
  321. store.basePost($h.U({
  322. c: 'special',
  323. a: 'viewing'
  324. }), {
  325. special_id: id,
  326. task_id: 0,
  327. total: this.duration * 1000,
  328. viewing_time: this.currentTime * 1000,
  329. percentage: Math.floor(this.currentTime / this.duration * 100)
  330. }, false, false, true);
  331. },
  332. // 播放/暂停音频
  333. toggleTask: function () {
  334. this.isPause = !this.isPause;
  335. },
  336. // 滑动音频
  337. moveTask: function (event) {
  338. if (this.player.getStatus() === 'playing') {
  339. this.isPause = true;
  340. this.player.pause();
  341. }
  342. var parentNode = event.target.parentNode.parentNode;
  343. var range = Math.floor((event.touches[0].pageX - parentNode.offsetLeft) / parentNode.clientWidth * 100);
  344. if (range > 100) {
  345. range = 100;
  346. }
  347. this.player.seek(this.duration * range / 100);
  348. },
  349. // 滑动音频停止
  350. moveEndTask: function () {
  351. if (this.player.getStatus() === 'pause') {
  352. this.isPause = false;
  353. this.player.play();
  354. }
  355. },
  356. changeVal: function (opt) {
  357. if (typeof opt !== 'object') {
  358. opt = {};
  359. }
  360. var action = opt.action || '';
  361. var value = opt.value || '';
  362. this[action] && this[action](value);
  363. },
  364. // 支付方式回调
  365. pay_order: function (data) {
  366. this.orderId = data.data.result.orderId || '';
  367. switch (data.data.status) {
  368. case "PAY_ERROR":
  369. case 'ORDER_EXIST':
  370. case 'ORDER_ERROR':
  371. this.extendOrder(data.msg);
  372. break;
  373. case 'WECHAT_PAY':
  374. this.wechatPay(data.data.result.jsConfig);
  375. break;
  376. case 'WECHAT_H5_PAY':
  377. this.payDialogOpen = false;
  378. var callbackUrl = callback_url + '?type=7&id=' + this.special.id;
  379. var mwebUrl = data.data.result.jsConfig.mweb_url + '&redirect_url=' + encodeURIComponent(callbackUrl);
  380. window.location.assign(mwebUrl);
  381. break;
  382. case 'SUCCESS':
  383. this.successOrder(data.msg);
  384. break;
  385. case 'ZHIFUBAO_PAY':
  386. window.location.assign($h.U({
  387. c: 'alipay',
  388. a: 'index',
  389. q: {
  390. info: data.data.result,
  391. params: 'special'
  392. }
  393. }));
  394. break;
  395. }
  396. },
  397. // 微信支付
  398. wechatPay: function (config) {
  399. var vm = this;
  400. mapleWx($jssdk(), function () {
  401. this.chooseWXPay(config, function () {
  402. vm.successOrder();
  403. }, {
  404. fail: vm.extendOrder,
  405. cancel: vm.extendOrder
  406. });
  407. });
  408. },
  409. // 支付成功
  410. successOrder: function (msg) {
  411. var that = this;
  412. $h.showMsg({
  413. title: msg || '支付成功',
  414. icon: 'success',
  415. success: function () {
  416. that.singleContent.isPay = true;
  417. that.payDialogOpen = false;
  418. that.$nextTick(function () {
  419. if (this.singleProfile.link) {
  420. this.createPlayer();
  421. } else if (this.singleProfile.videoId) {
  422. this.getPlayAuth();
  423. }
  424. });
  425. }
  426. });
  427. },
  428. // 支付未完成
  429. extendOrder: function (msg) {
  430. var that = this;
  431. if (typeof msg === 'object') {
  432. if (msg.errMsg === 'chooseWXPay:cancel') {
  433. msg = '微信支付取消';
  434. } else {
  435. msg = '支付失败';
  436. }
  437. } else {
  438. msg = '支付失败';
  439. }
  440. $h.pushMsg(msg, function () {
  441. that.payDialogOpen = false;
  442. if (that.orderId) {
  443. store.baseGet($h.U({
  444. c: 'special',
  445. a: 'del_order',
  446. q: {
  447. orderId: that.orderId
  448. }
  449. }));
  450. }
  451. });
  452. },
  453. },
  454. });
  455. });
  456. </script>
  457. {/block}