data_details.html 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  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"}{$title}{/block}
  12. {block name="head_top"}
  13. <style>
  14. body {
  15. padding-bottom: 1rem;
  16. padding-bottom: calc(1rem + constant(safe-area-inset-bottom));
  17. padding-bottom: calc(1rem + env(safe-area-inset-bottom));
  18. }
  19. .layui-layer-imgsee {
  20. display: none;
  21. }
  22. a[href^="tel"] {
  23. color: #191C6E;
  24. }
  25. </style>
  26. {/block}
  27. {block name="content"}
  28. <div v-cloak id="app">
  29. <div class="material-detail">
  30. <div class="header">
  31. <img :src="material.image" alt="">
  32. <div>
  33. <div>{{ material.title }}</div>
  34. <div>
  35. <div>
  36. <div>{{ material.ficti + material.sales }}人已下载</div>
  37. <div :class="{ money: material.pay_type }">
  38. <template v-if="material.pay_type">
  39. ¥<span>{{ material.money }}</span><span>¥{{ material.member_money }}</span>
  40. </template>
  41. <template v-else>
  42. 免费
  43. </template>
  44. </div>
  45. </div>
  46. <button type="button" @click="createShare">
  47. <i class="iconfont iconfenxiang"></i>
  48. <div>分享</div>
  49. </button>
  50. <button type="button" @click="collect">
  51. <i :class="['iconfont', material.collect ? 'iconshoucang2' : 'iconshoucang11']"></i>
  52. <div>{{ material.collect ? '已收藏' : '收藏' }}</div>
  53. </button>
  54. </div>
  55. </div>
  56. </div>
  57. <!-- 相关讲师 -->
  58. <related-lecturer v-if="lecturer" :lecturer="lecturer"></related-lecturer>
  59. <div class="main">
  60. <div>
  61. <div>详情</div>
  62. </div>
  63. <div v-html="material.abstract"></div>
  64. </div>
  65. <div class="footer">
  66. <button type="button" @click="goHome">
  67. <img src="{__WAP_PATH}zsff/images/special01.png" alt="">
  68. 首页
  69. </button>
  70. <button type="button" @click="customerService">
  71. <img src="{__WAP_PATH}zsff/images/special02.png" alt="">
  72. 客服
  73. </button>
  74. <button v-if="!material.pay_type || isPay || (!material.member_pay_type && is_member)" type="button" @click="download(1)">立即下载</button>
  75. <button v-else type="button" @click="buy">立即购买</button>
  76. </div>
  77. <div :class="{ mask: hasDialog }" @touchmove.prevent @click="hasDialog = false, type = 0"></div>
  78. <div v-if="(hasDialog && material.type == 1) || type == 1" class="android">
  79. <img src="{__WAP_PATH}zsff/images/material1.png" alt="">
  80. <div>{{ material.title }}</div>
  81. <button type="button" @click="download(2)">立即下载</button>
  82. </div>
  83. <div v-if="(hasDialog && material.type == 2) || type == 2" class="ios">
  84. <img src="{__WAP_PATH}zsff/images/material2.png" alt="">
  85. <div>复制下方链接及提取码到网盘下载</div>
  86. <div>
  87. <div>
  88. <div>链接:</div>
  89. <div><a :href="material.network_disk_link">{{ material.network_disk_link }}</a></div>
  90. </div>
  91. <div>
  92. <div>提取码:</div>
  93. <div>{{ material.network_disk_pwd }}</div>
  94. <button class="btn" type="button" :data-clipboard-text="'链接:' + material.network_disk_link + '\n提取码:' + material.network_disk_pwd">一键复制</button>
  95. </div>
  96. </div>
  97. </div>
  98. <!-- 登录弹窗 -->
  99. <base-login :login-show="loginShow" :site-name="site_name" @login-close="loginClose"></base-login>
  100. <!-- 支付弹窗 -->
  101. <pay-dialog :open.sync="payDialogOpen" :money="money" :now_money="now_money" :special_id="material.id" :pay_type_num="pay_type_num" :is-wechat="isWechat"
  102. :is-alipay="is_alipay" :is-balance="is_yue" :template-id="templateId" :wxpay-h5="wxpayH5" :is-member="is_member" :member-money="material.member_money"
  103. :member-link="memberLink" @change="changeVal">
  104. </pay-dialog>
  105. </div>
  106. </div>
  107. {/block}
  108. {block name="foot"}
  109. <script>
  110. window.overallShare = false;
  111. require([
  112. 'vue',
  113. 'clipboard',
  114. 'helper',
  115. 'store',
  116. 'components/pay-dialog/index',
  117. 'components/base-login/index',
  118. 'components/related-lecturer/index',
  119. 'layer',
  120. 'qrcode'
  121. ], function (Vue, ClipboardJS, $h, $http, PayDialog, BaseLogin, RelatedLecturer) {
  122. var material = {$data};
  123. console.log(material);
  124. var is_member = {$is_member};
  125. var isPay = {$isPay? 'true': 'false'};
  126. var site_url = "{$site_url}";
  127. var site_name = "{$Auth_site_name}";
  128. var isWechat = {$isWechat? 'true': 'false'};
  129. var now_money = {$now_money};
  130. var wxpayH5 = {$is_h5_wechat_payment_switch? 'true': 'false'};
  131. var is_alipay = {$is_alipay? 'true': 'false'};
  132. var is_yue = {$is_yue? 'true': 'false'};
  133. var callback_url = '{$callback_url}';
  134. var uid = {$userInfo['uid']? $userInfo['uid']: 0};
  135. var memberLink = "{:url('special/member_recharge')}";
  136. var vm = new Vue({
  137. el: '#app',
  138. components: {
  139. 'pay-dialog': PayDialog,
  140. 'base-login': BaseLogin,
  141. 'related-lecturer': RelatedLecturer
  142. },
  143. data: {
  144. material: material,
  145. is_member: is_member,
  146. isPay: isPay,
  147. isWechat: isWechat,
  148. isAndroid: window.navigator.userAgent.toLowerCase().indexOf('android') !== -1,
  149. hasDialog: false,
  150. isCollect: false,
  151. payDialogOpen: false, // 是否显示支付弹窗
  152. money: 0,
  153. now_money: now_money,
  154. link_pay_uid: '',
  155. pay_type_num: 70,
  156. is_alipay: is_alipay,
  157. is_yue: is_yue,
  158. templateId: '',
  159. wxpayH5: wxpayH5,
  160. loginShow: false,
  161. url: isWechat ? "{:url('index/login')}" : "{:url('login/phone_check')}",
  162. site_name: site_name,
  163. shareImage: '',
  164. lecturer: null,
  165. memberLink: memberLink,
  166. type: 0
  167. },
  168. created: function () {
  169. this.getLecturer();
  170. if (this.isWechat) {
  171. mapleWx($jssdk(), function () {
  172. this.onMenuShareAll({
  173. title: vm.material.title,
  174. desc: vm.material.title,
  175. imgUrl: vm.material.image,
  176. link: window.location.href + (window.location.search ? '&' : '?') + 'spread_uid=' + uid
  177. });
  178. });
  179. }
  180. },
  181. mounted: function () {
  182. this.$nextTick(function () {
  183. (!this.isAndroid || this.material.type) && this.initialCopy();
  184. });
  185. },
  186. methods: {
  187. // 实例化clipboard
  188. initialCopy: function () {
  189. this.clipboard = new ClipboardJS('.btn');
  190. this.clipboard.on('success', this.copySuccess);
  191. this.clipboard.on('error', this.copyError);
  192. },
  193. // 复制成功
  194. copySuccess: function (e) {
  195. $h.pushMsg('复制成功', function () {
  196. vm.hasDialog = false;
  197. vm.recordDownload();
  198. });
  199. e.clearSelection();
  200. },
  201. // 复制失败
  202. copyError: function () {
  203. $h.pushMsg('复制失败');
  204. },
  205. // 分享
  206. createShare: function () {
  207. if (this.shareImage) {
  208. this.layerPhoto();
  209. } else {
  210. $h.loadFFF();
  211. Promise.all([
  212. new Promise(function (resolve, reject) {
  213. var image = new Image();
  214. image.crossOrigin = 'anonymous';
  215. image.src = vm.material.poster_image + '?' + new Date().getTime();
  216. image.onload = function () {
  217. resolve(image);
  218. };
  219. image.onerror = function () {
  220. reject('error-image');
  221. };
  222. }),
  223. new Promise(function (resolve, reject) {
  224. resolve(new QRCode(document.createElement('canvas'), site_url));
  225. })
  226. ]).then(function (sources) {
  227. var canvas = document.createElement('canvas');
  228. var context = canvas.getContext('2d');
  229. canvas.width = 600;
  230. canvas.height = 960;
  231. context.fillStyle = '#FFFFFF';
  232. context.fillRect(0, 0, 600, 960);
  233. context.drawImage(sources[0], 0, 0, 600, 740);
  234. context.drawImage(sources[1]._el.firstElementChild, 108, 775, 150, 150);
  235. context.font = '22px sans-serif';
  236. context.fillStyle = '#999999';
  237. context.textBaseline = 'top';
  238. var text = '邀您加入' + site_name;
  239. var list = [];
  240. var start = 0;
  241. for (var i = 0; i <= text.length; i++) {
  242. if (context.measureText(text.slice(start, i)).width > 198) {
  243. list.push(text.slice(start, i - 1));
  244. start = i - 1;
  245. }
  246. }
  247. if (start !== text.length) {
  248. list.push(text.slice(start));
  249. }
  250. if (list.length > 3) {
  251. list.length = 3;
  252. for (var j = 0; j <= list[2].length; j++) {
  253. if (context.measureText(list[2].slice(0, j) + '……').width > 198) {
  254. list[2] = list[2].slice(0, j - 1) + '……';
  255. break;
  256. }
  257. }
  258. }
  259. list.push('长按识别或扫码进入');
  260. for (var k = 0; k < list.length; k++) {
  261. context.fillText(list[k], 294, 775 + (150 / list.length) * k);
  262. }
  263. $h.loadClear();
  264. vm.shareImage = canvas.toDataURL('image/jpeg');
  265. vm.layerPhoto();
  266. canvas = null;
  267. }).catch(function (err) {
  268. $h.loadClear();
  269. $h.pushMsg(err);
  270. });
  271. }
  272. },
  273. // 收藏
  274. collect: function () {
  275. $h.loadFFF();
  276. $http.baseGet($h.U({
  277. c: 'material',
  278. a: 'collect',
  279. q: {
  280. id: this.material.id
  281. }
  282. }), function (res) {
  283. $h.loadClear();
  284. vm.material.collect = !vm.material.collect;
  285. $h.pushMsg(vm.material.collect ? '收藏成功' : '取消收藏成功');
  286. }, function () {
  287. $h.loadClear();
  288. });
  289. },
  290. // 购买
  291. buy: function () {
  292. $http.baseGet($h.U({c: 'index', a: 'user_login'}), function () {
  293. this.money = this.is_member ? this.material.member_money : this.material.money;
  294. this.payDialogOpen = true;
  295. }.bind(this), function () {
  296. this.loginShow = true;
  297. }.bind(this));
  298. },
  299. // 下载
  300. download: function (type) {
  301. var vm = this;
  302. if (type === 1) {
  303. if (this.material.type) {
  304. this.hasDialog = true;
  305. } else {
  306. layer.open({
  307. title: false,
  308. closeBtn: false,
  309. content: '请选择下载方式',
  310. btn: ['本地下载', '网盘下载', '取消'],
  311. yes: function (index) {
  312. vm.hasDialog = true;
  313. vm.type = 1;
  314. layer.close(index);
  315. },
  316. btn2: function () {
  317. vm.hasDialog = true;
  318. vm.type = 2;
  319. }
  320. });
  321. }
  322. } else {
  323. vm.recordDownload();
  324. window.open(this.material.link);
  325. }
  326. },
  327. changeVal: function (opt) {
  328. if (typeof opt !== 'object') {
  329. opt = {};
  330. }
  331. var action = opt.action || '';
  332. var value = opt.value || '';
  333. this[action] && this[action](value);
  334. },
  335. //关闭登录
  336. loginClose: function (value) {
  337. this.loginShow = false;
  338. value && this.logComplete();
  339. },
  340. // 登录完成回调事件
  341. logComplete: function () {
  342. $h.loadFFF();
  343. $http.baseGet($h.U({
  344. c: 'special',
  345. a: 'isMember'
  346. }), function (res) {
  347. var data = res.data.data;
  348. vm.is_member = data.is_member;
  349. vm.now_money = data.now_money;
  350. });
  351. },
  352. // 支付完成后回调事件
  353. pay_order: function (data) {
  354. this.orderId = data.data.result.orderId || '';
  355. switch (data.data.status) {
  356. case 'PAY_ERROR':
  357. case 'ORDER_EXIST':
  358. case 'ORDER_ERROR':
  359. this.extendOrder(data.msg);
  360. break;
  361. case 'WECHAT_PAY':
  362. this.wechatPay(data.data.result.jsConfig);
  363. break;
  364. case 'WECHAT_H5_PAY':
  365. this.payDialogOpen = false;
  366. window.location.assign(data.data.result.jsConfig.mweb_url + 'redirect_url=' + encodeURIComponent(callback_url + '?type=8&id=' + this.material.id));
  367. break;
  368. case 'SUCCESS':
  369. this.successOrder(data.msg);
  370. break;
  371. case 'ZHIFUBAO_PAY':
  372. window.location.assign($h.U({
  373. c: 'alipay',
  374. a: 'index',
  375. q: {
  376. info: data.data.result,
  377. params: 'datadownload'
  378. }
  379. }));
  380. break;
  381. }
  382. },
  383. extendOrder: function (msg) {
  384. if (typeof msg === 'object' && msg.errMsg === 'chooseWXPay:cancel') {
  385. msg = '微信支付取消';
  386. } else {
  387. msg = '支付失败';
  388. }
  389. $h.pushMsg(msg, function () {
  390. vm.payDialogOpen = false;
  391. if (vm.orderId) {
  392. $http.baseGet($h.U({
  393. c: 'special',
  394. a: 'del_order',
  395. q: {
  396. orderId: vm.orderId
  397. }
  398. }));
  399. }
  400. });
  401. },
  402. wechatPay: function (config) {
  403. mapleWx($jssdk(), function () {
  404. this.chooseWXPay(config, function () {
  405. vm.successOrder();
  406. }, {
  407. fail: vm.extendOrder,
  408. cancel: vm.extendOrder
  409. });
  410. });
  411. },
  412. successOrder: function (msg) {
  413. $h.showMsg({
  414. title: msg ? msg : '支付成功',
  415. icon: 'success',
  416. success: function () {
  417. vm.payDialogOpen = false;
  418. vm.isPay = true;
  419. }
  420. });
  421. },
  422. goHome: function () {
  423. window.location.href = "{:url('index/index')}";
  424. },
  425. // 联系客服
  426. customerService: function () {
  427. $http.baseGet($h.U({
  428. c: 'public_api',
  429. a: 'public_data'
  430. }), function (res) {
  431. var data = res.data.data;
  432. if (data.customer_service === '3') {
  433. if (data.site_service_phone) {
  434. layer.confirm('是否拨打 <a href="tel:' + data.site_service_phone + '">' + data.site_service_phone + '</a> 进行咨询?', {
  435. title: false,
  436. closeBtn: false,
  437. btn: ['拨打', '取消']
  438. }, function (index) {
  439. window.location.assign('tel:' + data.site_service_phone);
  440. layer.close(index);
  441. });
  442. } else {
  443. layer.msg('抱歉,无法联系客服');
  444. }
  445. } else {
  446. window.location.assign($h.U({
  447. c: 'service',
  448. a: 'service_list'
  449. }));
  450. }
  451. });
  452. },
  453. recordDownload: function () {
  454. $http.baseGet($h.U({
  455. c: 'material',
  456. a: 'userDownload',
  457. q: {
  458. id: this.material.id
  459. }
  460. }), function () {
  461. vm.material.sales++;
  462. });
  463. },
  464. layerPhoto: function (src) {
  465. layer.photos({
  466. photos: {
  467. data: [
  468. {
  469. src: this.shareImage
  470. }
  471. ]
  472. },
  473. anim: 5
  474. });
  475. },
  476. // 相关讲师
  477. getLecturer: function () {
  478. var vm = this;
  479. $http.baseGet($h.U({
  480. c: 'auth_api',
  481. a: 'getLecturer',
  482. q: {
  483. mer_id: this.material.mer_id
  484. }
  485. }), function (res) {
  486. vm.lecturer = res.data.data;
  487. });
  488. }
  489. }
  490. });
  491. });
  492. </script>
  493. {/block}