index.html 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. <!doctype html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  5. <title>{$html_title|default=$Think.config.ds_config.site_name}</title>
  6. <meta name="renderer" content="webkit|ie-comp|ie-stand" />
  7. <meta name="keywords" content="{$seo_keywords|default=''}" />
  8. <meta name="description" content="{$seo_description|default=''}" />
  9. <script>
  10. var BASESITEROOT = "{$Think.BASE_SITE_ROOT}";
  11. var HOMESITEROOT = "{$Think.HOME_SITE_ROOT}";
  12. var BASESITEURL = "{$Think.BASE_SITE_URL}";
  13. var HOMESITEURL = "{$Think.HOME_SITE_URL}";
  14. var TIMESTAMP = "{$Think.TIMESTAMP}";
  15. </script>
  16. <!--{if $live_apply_info.video_type!='tencent'}-->
  17. <link rel="stylesheet" href="https://g.alicdn.com/de/prismplayer/2.8.8/skins/default/aliplayer-min.css" />
  18. <script type="text/javascript" charset="utf-8" src="https://g.alicdn.com/de/prismplayer/2.8.8/aliplayer-min.js"></script>
  19. <!--{else}-->
  20. <!--{if $active}-->
  21. <script src="//imgcache.qq.com/open/qcloud/video/vcplayer/TcPlayer-2.3.3.js" charset="utf-8"></script>
  22. <!--{else}-->
  23. <link href="https://imgcache.qq.com/open/qcloud/video/tcplayer/tcplayer.css" rel="stylesheet">
  24. <!--如果需要在 Chrome 和 Firefox 等现代浏览器中通过 H5 播放 HLS 格式的视频,需要在 tcplayer.v4.1.min.js 之前引入 hls.min.0.13.2m.js。-->
  25. <script src="https://imgcache.qq.com/open/qcloud/video/tcplayer/libs/hls.min.0.13.2m.js"></script>
  26. <!--播放器脚本文件-->
  27. <script src="https://imgcache.qq.com/open/qcloud/video/tcplayer/tcplayer.v4.1.min.js"></script>
  28. <!--{/if}-->
  29. <!--{/if}-->
  30. <script src="{$Think.PLUGINS_SITE_ROOT}/jquery-2.1.4.min.js"></script>
  31. <script src="{$Think.PLUGINS_SITE_ROOT}/layer/layer.js"></script>
  32. </head>
  33. <body class="room ">
  34. <script src="{$Think.HOME_SITE_ROOT}/js/live_detail.js"></script>
  35. <link rel="stylesheet" href="{$Think.HOME_SITE_ROOT}/css/live_detail.css">
  36. <div>
  37. <div class="left_bar" id="J_left_bar" style="display: block;">
  38. <div class="logo">
  39. <a href="{$Think.HOME_SITE_URL}" target="_blank" style='background-image:url({if $Think.config.ds_config.seller_center_logo == ''}{$Think.BASE_SITE_ROOT}/uploads/home/common/seller_center_logo.png{else}{:ds_get_pic(ATTACH_COMMON,$Think.config.ds_config.seller_center_logo)}{/if})'></a>
  40. </div>
  41. <div class="avatar J_layerlogin">
  42. <a href="{:url('Member/index')}" target="_blank"><img src="{$member_avatar}" id="J_my_avatar" /></a>
  43. </div>
  44. <div class="bot">
  45. <div class="download">
  46. <div>
  47. <i class="iconfont">&#xe601;</i>
  48. <span>{$Think.lang.view_at_phone}</span>
  49. </div>
  50. <div class="s_download_box">
  51. <div class="content">
  52. <div class="download_ecode">
  53. <img src="{:url('Qrcode/index',['url'=>config('ds_config.h5_site_url').'/member/live_detail?live_apply_id='.$live_apply_info['live_apply_id']])}" alt="" />
  54. </div>
  55. </div>
  56. </div>
  57. </div>
  58. </div>
  59. </div>
  60. <div class="live_box" id="J_live_box" style="height: 900px; margin-top: -450px; ">
  61. <div class="w330">
  62. <div class="anchorinfo clearfix pr" id="J_anchorinfo">
  63. <div class="avatar J_u_card">
  64. <a href="{:url('Store/index',['store_id'=>$live_apply_info['live_apply_user_id']])}" target="_blank"> <img src="{$live_apply_info.live_apply_user_avatar}" /> </a>
  65. <div class="authentication"></div>
  66. </div>
  67. <div class="info">
  68. <div class="nickname level_right">
  69. <a href="{:url('Store/index',['store_id'=>$live_apply_info['live_apply_user_id']])}" target="_blank">{$live_apply_info.live_apply_user_name}</a>
  70. </div>
  71. <div class="id">
  72. {$live_apply_info.area_info}
  73. </div>
  74. </div>
  75. <div id="follow_330" onclick="follow()" class="{if $live_apply_info.is_favorate}true_follow{else}follow_zi{/if} J_follow x_guide"></div>
  76. </div>
  77. {if $live_apply_info.goods_list}
  78. <div class="goods-list">
  79. {foreach name='live_apply_info.goods_list' item='goods'}
  80. <div class="goods-item">
  81. <div class="left">
  82. <a href="{:url('Goods/index',['goods_id'=>$goods['goods_id']])}" target="_blank"><img class="goods-image" src="{$goods.goods_image}"></a>
  83. </div>
  84. <div class="right">
  85. <div class="goods-name"><a href="{:url('Goods/index',['goods_id'=>$goods['goods_id']])}" target="_blank">{$goods.goods_name}</a></div>
  86. <div class="goods-info">
  87. <div class="goods-price">{$goods.goods_price}{$Think.lang.ds_yuan}</div>
  88. <div class="iconfont cart-btn" onclick='addCart({$goods.goods_id})'>&#xe6c9;</div>
  89. </div>
  90. </div>
  91. </div>
  92. {/foreach}
  93. </div>
  94. {/if}
  95. </div>
  96. <!-- .w330 -->
  97. <div class="w400" id="J_w400" style="overflow: hidden;">
  98. <div class="content flash" id="J_flash" style="margin-left: 0px;">
  99. {if $active}
  100. <div id="id_test_video" style="width:100%; height:100%;"></div>
  101. {else}
  102. {if $live_apply_info.live_apply_video}
  103. <!--{if $live_apply_info.video_type=='tencent'}-->
  104. <video controls controlslist="nodownload" {if !$live_apply_info.file_id && $live_apply_info.live_apply_video}src="{$live_apply_info.live_apply_video}"{/if} id="id_test_video" autoplay="" style="width:100%;height:100%;"></video>
  105. <!--{else}-->
  106. <div id="id_test_video" style="width:100%; height:100%;"></div>
  107. <!--{/if}-->
  108. {else}
  109. <div style="position:absolute;text-align: center;top:50%;font-size:20px;width:100%;">
  110. {$Think.lang.live_not_online}{$live_apply_info.live_apply_push_message}
  111. </div>
  112. {/if}
  113. {/if}
  114. </div>
  115. <div class="heart" id="heart" onclick="addLike()"></div>
  116. <div class="cover" id="J_cover">
  117. <!-- ///.goldcoin -->
  118. <div class="giftlist" id="J_continue_gift_1">
  119. </div>
  120. <!-- .giftlist -->
  121. </div>
  122. </div>
  123. <!-- .w400 -->
  124. <div class="w360">
  125. <div class="msglist J_scroll" id="J_msglist" style="overflow: hidden; outline: none;">
  126. </div>
  127. <div class="msgform" id="J_msgform">
  128. <div class="danmu on" id="J_send_danmu" onclick='toggleDanmu()'>
  129. </div>
  130. <input type="text" id='message_content' class="text" maxlength="30" placeholder="{$Think.lang.chat_with_video_user}" />
  131. <input type="text" class="send" value="{$Think.lang.send}" id="J_comment" onclick='sendMessage()' />
  132. <!-- <form action="#"></form> -->
  133. </div>
  134. <div class="gift" id="J_giftaction">
  135. <div class="gift_window">
  136. <div class="window">
  137. <div class="giftlist">
  138. <div class="gift_move">
  139. <div class="mark">
  140. <div>
  141. <span class="" onclick='$(this).toggleClass("on")'>
  142. <img class="img" src="{$Think.HOME_SITE_ROOT}/images/live/gift-item.png" />
  143. <i class='point'>100{$Think.lang.points_unit}</i>
  144. </span>
  145. <span class=""></span>
  146. <span class=""></span>
  147. <span class=""></span>
  148. <span class=""></span>
  149. <span class=""></span>
  150. <span class=""></span>
  151. <span class=""></span>
  152. <span class=""></span>
  153. <span class=""></span>
  154. </div>
  155. </div>
  156. </div>
  157. </div>
  158. <div class="half_mark"></div>
  159. </div>
  160. </div>
  161. <div class="giftform" id="J_gift_form">
  162. <div class="coin">
  163. {$Think.lang.points_unit}:
  164. <span id="J_mygoldcoin"><span class="J_layerlogin" id='member_points'>{$member_points}</span></span>
  165. </div>
  166. <div class="form">
  167. <span>{$Think.lang.number}</span>
  168. <input type="text" class="text" value="1" id="J_gift_num" />
  169. <button class="btn" id="J_send_gift" onclick='addGift()'>{$Think.lang.give}</button>
  170. </div>
  171. </div>
  172. </div>
  173. </div>
  174. <!-- .w360 -->
  175. </div>
  176. <!-- .live_box -->
  177. <div style="width: 1000px; height:540px;"></div>
  178. </div>
  179. <script>
  180. var canReconnect=true
  181. var canLike = true
  182. var ifConnect=false
  183. var ws
  184. var lockReconnect=false
  185. var timeOut=false
  186. var giftList=new Array()
  187. function toggleDanmu(){
  188. if($('#J_send_danmu').hasClass('on')){
  189. $('#J_send_danmu').removeClass('on')
  190. $('#J_msglist').hide()
  191. }else{
  192. $('#J_send_danmu').addClass('on')
  193. $('#J_msglist').show()
  194. }
  195. }
  196. function addGift(){
  197. {if !$active}
  198. return
  199. {/if}
  200. if(!$('#J_giftaction .giftlist .on')){
  201. layer.msg('{$Think.lang.gift_empty}')
  202. }
  203. var num=parseInt($('#J_gift_num').val())
  204. if(isNaN(num) || num<1){
  205. layer.msg('{$Think.lang.num_error}')
  206. }
  207. $.getJSON('{:url("MemberLive/add_gift")}',{live_apply_id:{$live_apply_info.live_apply_id},num:num},function(res){
  208. if(res.code!=10000){
  209. layer.msg(res.message)
  210. }else{
  211. $('#member_points').text(res.result.member_points)
  212. }
  213. })
  214. }
  215. function addLike() {
  216. {if !$active}
  217. return
  218. {/if}
  219. if (!canLike) {
  220. return
  221. }
  222. canLike = false
  223. $("#heart").addClass('heartAnimation')
  224. setTimeout(function () {
  225. canLike = true
  226. $("#heart").removeClass('heartAnimation')
  227. }, 800)
  228. $.getJSON('{:url("MemberLive/add_like")}',{live_apply_id:{$live_apply_info.live_apply_id}},function(res){
  229. })
  230. }
  231. function follow(){
  232. $.getJSON('{:url("Memberfavorites/favoritesstore")}',{fid:{$live_apply_info.live_apply_user_id}},function(res){
  233. if(!res.done){
  234. layer.msg(res.msg)
  235. }else{
  236. $('#follow_330').toggleClass('follow_zi')
  237. $('#follow_330').toggleClass('true_follow')
  238. }
  239. })
  240. }
  241. function addCart(goods_id){
  242. $.getJSON('{:url("Cart/add")}',{goods_id:goods_id,quantity:1},function(res){
  243. if(!res.state){
  244. layer.msg(res.msg)
  245. }else{
  246. layer.msg('{$Think.lang.ds_common_op_succ}')
  247. }
  248. })
  249. }
  250. $(function () {
  251. /*{if $active}*/
  252. /*{if $Think.config.ds_config.video_type=='tencent'}*/
  253. var player = new TcPlayer('id_test_video', {
  254. 'm3u8_hd': '{$live_apply_info.live_apply_play_url}', // 请替换成实际可用的播放地址
  255. 'autoplay': true, // iOS 下 safari 浏览器,以及大部分移动端浏览器是不开放视频自动播放这个能力的
  256. 'live': true,
  257. 'controls': 'system',
  258. // 'systemFullscreen': true,
  259. 'width': 499,
  260. 'height': 900,
  261. 'x5_player': true,
  262. 'x5_type': 'h5',
  263. // 'x5_fullscreen': 'true',
  264. 'listener': function (res) {
  265. if (res.type == 'error') {
  266. var index=layer.confirm("{$Think.lang.live_error}", {
  267. btn: ['{$Think.lang.ds_ok}', '{$Think.lang.ds_cancel}'],
  268. title: false,
  269. }, function () {
  270. layer.close(index)
  271. window.location.href = "{:url('Live/index')}";
  272. })
  273. }
  274. }
  275. })
  276. /*{else}*/
  277. var player = new Aliplayer({
  278. "id": "id_test_video",
  279. "source": "{$live_apply_info.live_apply_play_url}",
  280. "width": "100%",
  281. "height": "100%",
  282. "autoplay": true,
  283. "isLive": true,
  284. "rePlay": false,
  285. "playsinline": true,
  286. "preload": true,
  287. "controlBarVisibility": "hover",
  288. "useH5Prism": true
  289. }, function (player) {
  290. player.on('liveStreamStop',function(){
  291. var index=layer.confirm("{$Think.lang.live_error}", {
  292. btn: ['{$Think.lang.ds_ok}', '{$Think.lang.ds_cancel}'],
  293. title: false,
  294. }, function () {
  295. layer.close(index)
  296. window.location.href = "{:url('Live/index')}";
  297. })
  298. });
  299. }
  300. );
  301. /*{/if}*/
  302. createWebSocket()
  303. /*{else}*/
  304. /*{if $live_apply_info.live_apply_video}*/
  305. /*{if $live_apply_info.video_type=='tencent'}*/
  306. var player = TCPlayer('id_test_video', {
  307. fileID: '{$live_apply_info.file_id}', // 请传入需要播放的视频 filID(必须)
  308. appID: '{$Think.config.ds_config.vod_tencent_appid}', // 请传入点播账号的 appID(必须)
  309. flash:{
  310. swf: '//{$Think.config.ds_config.vod_tencent_play_domain}/vod-player/{$Think.config.ds_config.vod_tencent_appid}/{$live_apply_info.file_id}/tcplayer/player.swf' //swf 文件地址(必须)
  311. },
  312. plugins:{
  313. ContinuePlay: { // 开启续播功能
  314. auto: true, //[可选] 是否在视频播放后自动续播
  315. },
  316. },
  317. psign:'{$live_apply_info.psign|default=""}'
  318. });
  319. /*{else}*/
  320. var player = new Aliplayer({
  321. "id": "id_test_video",
  322. "source": "{$live_apply_info.live_apply_video}",
  323. "width": "100%",
  324. "height": "100%",
  325. "autoplay": true,
  326. "isLive": false,
  327. "rePlay": false,
  328. "playsinline": true,
  329. "preload": true,
  330. "controlBarVisibility": "hover",
  331. "useH5Prism": true
  332. }, function (player) {
  333. }
  334. );
  335. /*{/if}*/
  336. /*{/if}*/
  337. /*{/if}*/
  338. })
  339. function sendMessage() {
  340. {if !$active}
  341. return
  342. {/if}
  343. var data=$('#message_content').val()
  344. if (!ifConnect) {
  345. layer.msg('{$Think.lang.chat_system_error}')
  346. return
  347. }
  348. if (!data) {
  349. layer.msg('{$Think.lang.message_empty}')
  350. return
  351. }
  352. $.getJSON('{:url("MemberInstantMessage/add")}',{
  353. to_id:{$live_apply_info.live_apply_id},
  354. to_type: 2,
  355. message: data,
  356. message_type: 0
  357. },function(res){
  358. layer.msg(res.message)
  359. if(res.code==10000){
  360. $('#message_content').val('')
  361. }
  362. })
  363. }
  364. function createWebSocket() {
  365. try {
  366. ws = new WebSocket('{$live_apply_info.instant_message_url}')
  367. init()
  368. } catch (e) {
  369. reconnect()
  370. }
  371. }
  372. function init() {
  373. ws.onopen = wsOpen
  374. ws.onmessage = wsMessage
  375. ws.onclose = wsClose
  376. ws.onerror = wsError
  377. }
  378. function reconnect() {
  379. if (lockReconnect) {
  380. return
  381. }
  382. lockReconnect = true
  383. // 没连接上会一直重连,设置延迟避免请求过多
  384. timeOut && clearTimeout(timeOut)
  385. timeOut = setTimeout(function () {
  386. createWebSocket()
  387. lockReconnect = false
  388. }, 4000)
  389. }
  390. function wsOpen() {
  391. ifConnect = true
  392. // 心跳检测重置
  393. heartCheck.start()
  394. }
  395. function wsMessage(res) {
  396. var message = JSON.parse(res.data)
  397. if (!message) {
  398. layer.msg('{$Think.lang.message_transfer_fail}{$Think.lang.ds_colon}' + res.data)
  399. return
  400. }
  401. var type = message.type || ''
  402. switch (type) {
  403. // Events.php中返回的init类型的消息,将client_id发给后台进行uid绑定
  404. case 'init':
  405. var clientId = message.client_id
  406. $.getJSON('{:url("MemberLive/join_live")}',{live_apply_id:{$live_apply_info.live_apply_id},client_id:clientId}, function(res){
  407. if(res.code!=10000){
  408. layer.msg(res.message)
  409. }
  410. })
  411. break
  412. case 'leave':
  413. break
  414. case 'join':
  415. break
  416. case 'gift':
  417. var randnum=parseInt(Math.random()*10000)
  418. var html=''
  419. html+='<div class="gift" id="gift_'+randnum+'">'
  420. html+=' <div class="mark">'
  421. html+=' <img src="'+message.member.member_avatar+'" alt="" class="avatar">'
  422. html+=' <div class="info J_u_card">'
  423. html+=' <span class="nickname level_left"><span class="level_16 level"> </span>'+message.member.member_name+'</span>'
  424. html+=' <div class="detail">'
  425. html+=' {$Think.lang.give_out}'
  426. html+=' <span>{$Think.lang.rocket}</span><span>×'+message.gift_num+'</span>'
  427. html+=' </div>'
  428. html+=' </div>'
  429. html+=' </div>'
  430. html+=' <div class="effect"> '
  431. html+=' <img src="{$Think.HOME_SITE_ROOT}/images/live/gift-item.png" alt="">'
  432. html+=' </div>'
  433. html+='</div>'
  434. $('#J_continue_gift_1').append(html)
  435. giftList.push(randnum)
  436. setTimeout(() => {
  437. $('#gift_'+giftList.shift()).remove();
  438. }, 1000)
  439. break
  440. default:
  441. var html='';
  442. html+='<div class="msg_1 J_u_card">'
  443. html+=' <div class="avatar">'
  444. html+=' <img src="'+message.instant_message_from_avatar+'" alt="" />'
  445. html+=' </div>'
  446. html+=' <div class="info">'
  447. html+=' <div class="clearfix">'
  448. html+=' <span class="nickname fl ">'+message.instant_message_from_name+'</span>'
  449. html+=' </div>'
  450. html+=' <div class="content">'
  451. html+=message.instant_message
  452. html+=' </div>'
  453. html+=' </div>'
  454. html+=' </div>'
  455. $('#J_msglist').append(html)
  456. $("#J_msglist").scrollTop($("#J_msglist").innerHeight());
  457. }
  458. heartCheck.start()
  459. }
  460. function wsClose(res) {
  461. ifConnect = false
  462. if (res.reason) {
  463. layer.msg('{$Think.lang.chat_system_disconnect}{$Think.lang.colon}' + res.reason)
  464. }
  465. if(canReconnect){
  466. reconnect()
  467. }
  468. }
  469. function wsError(res) {
  470. layer.msg(res.errMsg)
  471. reconnect()
  472. }
  473. // 心跳检测
  474. var heartCheck = {
  475. timeout: 3000,
  476. timeoutObj: null,
  477. start: function () {
  478. var self = this
  479. this.timeoutObj && clearInterval(this.timeoutObj)
  480. this.timeoutObj = setInterval(function () {
  481. // 这里发送一个心跳,后端收到后,返回一个心跳消息,
  482. ws.send('123456789')
  483. }, this.timeout)
  484. },
  485. stop:function(){
  486. this.timeoutObj && clearInterval(this.timeoutObj)
  487. }
  488. }
  489. </script>