special_live.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. {extend name="public/container"}
  2. {block name='head_top'}
  3. <style>
  4. .go-live{width: 100%;background-color: #eeeeee;display: none;}
  5. .go-live .live-box{padding: 10px 0 10px 30px;background-color: #ffffff;border-radius: 5px;margin-top: 30px;}
  6. .go-live .live-box .live-text{font-size: 15px;color: #0092DC;margin: 5px;padding: 10px 0;}
  7. .go-live .live-box .live-title{text-align: center;}
  8. .go-live .live-box .live-text p{color:#333333;padding:10px;display: inline-block;width: 80%;background-color: #eeeeee;border-radius: 10px;}
  9. .go-live .live-box .live-text label{width: 8%;}
  10. </style>
  11. {/block}
  12. {block name="content"}
  13. <div class="layui-fluid">
  14. <div class="layui-row layui-col-space15">
  15. <div class="layui-col-md12">
  16. <div class="layui-card">
  17. <div class="layui-card-body">
  18. <div class="layui-row layui-col-space15" id="app">
  19. <div class="layui-col-md12">
  20. <div class="layui-tab layui-tab-brief" lay-filter="tab">
  21. <ul class="layui-tab-title">
  22. <li lay-id="list" {eq name='type' value='1'}class="layui-this" {/eq} >
  23. <a href="{eq name='type' value='1'}javascript:;{else}{:Url('special_live',['special_type'=>4,'type'=>1])}{/eq}">直播列表</a>
  24. </li>
  25. <li lay-id="list" {eq name='type' value='2'}class="layui-this" {/eq}>
  26. <a href="{eq name='type' value='2'}javascript:;{else}{:Url('index',['special_type'=>4,'type'=>2])}{/eq}">直播间管理</a>
  27. </li>
  28. </ul>
  29. </div>
  30. </div>
  31. <div class="layui-col-md12">
  32. <form class="layui-form layui-form-pane" action="">
  33. <div class="layui-form-item">
  34. <div class="layui-inline">
  35. <label class="layui-form-label">直播搜索</label>
  36. <div class="layui-input-block">
  37. <input type="text" name="store_name" class="layui-input" placeholder="直播标题,简介,短语,编号">
  38. <input type="hidden" name="type" value="{$type}">
  39. <input type="hidden" name="subject_id" value="{$subject_id}">
  40. </div>
  41. </div>
  42. <div class="layui-inline">
  43. <label class="layui-form-label">课程分类</label>
  44. <div class="layui-input-block">
  45. <select name="subject_id" lay-search="">
  46. <option value="0">全部</option>
  47. {volist name='subject_list' id='vo'}
  48. <optgroup label="{$vo.name}">{$vo.name}
  49. {volist name='$vo.special_subject' id='vc'}
  50. <option value="{$vc.id}">|----{$vc.name}</option>
  51. {/volist}
  52. </optgroup>
  53. {/volist}
  54. </select>
  55. </div>
  56. </div>
  57. <div class="layui-inline">
  58. <label class="layui-form-label">显示状态</label>
  59. <div class="layui-input-block">
  60. <select name="is_show">
  61. <option value="">全部</option>
  62. <option value="1">显示</option>
  63. <option value="0">隐藏</option>
  64. </select>
  65. </div>
  66. </div>
  67. <div class="layui-inline">
  68. <label class="layui-form-label">时间范围</label>
  69. <div class="layui-input-inline" style="width: 260px;">
  70. <input type="text" name="datetime" class="layui-input" id="datetime" placeholder="时间范围">
  71. </div>
  72. </div>
  73. <div class="layui-inline">
  74. <div class="layui-input-inline">
  75. <button class="layui-btn layui-btn-sm layui-btn-normal" lay-submit="search" lay-filter="search">
  76. <i class="layui-icon layui-icon-search"></i>搜索</button>
  77. </div>
  78. </div>
  79. </div>
  80. </form>
  81. </div>
  82. <!--产品列表-->
  83. <div class="layui-col-md12">
  84. <div class="layui-btn-group">
  85. <button type="button" class="layui-btn layui-btn-normal layui-btn-sm" onclick="action.open_add('{:Url('/admin/special.special_type/add',['special_type' =>$special_type])}','添加{$special_title}')"><i class="layui-icon">&#xe608;</i> 添加{$special_title}</button>
  86. <button type="button" class="layui-btn layui-btn-normal layui-btn-sm" onclick="window.location.reload()"><i class="layui-icon">&#xe669;</i> 刷新</button>
  87. </div>
  88. <table class="layui-hide" id="List" lay-filter="List"></table>
  89. <script type="text/html" id="recommend">
  90. {{# layui.each(d.recommend, function(index, item){ }}
  91. <span class="layui-badge layui-bg-blue recom-item" data-id="{{index}}" data-pid="{{d.id}}">{{item}}</span>
  92. {{# }); }}
  93. </script>
  94. <script type="text/html" id="is_pink">
  95. {{# if(d.is_pink){ }}
  96. <span class="layui-badge layui-bg-blue">开启</span>
  97. {{# }else{ }}
  98. <span class="layui-badge">关闭</span>
  99. {{# } }}
  100. </script>
  101. <script type="text/html" id="is_show">
  102. <input type='checkbox' name='id' lay-skin='switch' value="{{d.id}}" lay-filter='is_show' lay-text='显示|隐藏' {{ d.is_show == 1 ? 'checked' : '' }}>
  103. </script>
  104. <script type="text/html" id="image">
  105. <img style="cursor: pointer;" height="50" lay-event='open_image' src="{{d.image}}">
  106. </script>
  107. <script type="text/html" id="act">
  108. <button type="button" class="layui-btn layui-btn-normal layui-btn-xs" onclick="dropdown(this)">
  109. <i class="layui-icon">&#xe625;</i> 操作
  110. </button>
  111. <ul class="layui-nav-child layui-anim layui-anim-upbit">
  112. <li>
  113. <a href="javascript:void(0)" onclick="action.open_add('{:Url('/admin/special.special_type/add')}?id={{d.id}}&special_type={$special_type}','编辑直播')" >
  114. <i class="fa fa-paste"></i> 编辑直播
  115. </a>
  116. </li>
  117. <li>
  118. <a href="javascript:void(0)" lay-event='go_live'>
  119. <i class="fa fa-video-camera"></i> 去直播
  120. </a>
  121. </li>
  122. {if condition='isset($login_role["sign"]) && $login_role["sign"] eq "admin"'}
  123. <li>
  124. <a href="javascript:void(0)" lay-event='move_live_admin'>
  125. <i class="fa fa-street-view"></i> 直播间转让
  126. </a>
  127. </li>
  128. {/if}
  129. <li>
  130. <a href="javascript:void(0)" onclick="$eb.createModalFrame('{{d.title}}-推荐管理','{:Url('special.special_type/recommend')}?special_id={{d.id}}',{h:300,w:400})">
  131. <i class="fa fa-check-circle"></i> 推荐至首页
  132. </a>
  133. </li>
  134. {{# if(d.is_play){ }}
  135. <li>
  136. <a lay-event='recommend' href="javascript:void(0)">
  137. <i class="fa fa-check-circle"></i> 首页弹窗
  138. </a>
  139. </li>
  140. {{# } }}
  141. <li>
  142. <a href="javascript:void(0)" onclick="$eb.createModalFrame('{{d.title}}-拼团管理','{:Url('special.special_type/pink')}?special_id={{d.id}}',{h:500})">
  143. <i class="fa fa-users"></i> 拼团设置
  144. </a>
  145. </li>
  146. {{# if(d.is_pink){ }}
  147. <li>
  148. <a href="{:Url('ump.store_combination/combina_list')}?cid={{d.id}}&special_type={$special_type}" >
  149. <i class="fa fa-street-view"></i> 查看拼团
  150. </a>
  151. </li>
  152. {{# } }}
  153. <li>
  154. <a href="javascript:void(0)" onclick="$eb.createModalFrame('{{d.title}}-直播回放','{:Url('download_list')}?special_id={{d.id}}',{w:1200})">
  155. <i class="fa fa-cloud-download"></i> 直播回放
  156. </a>
  157. </li>
  158. <li>
  159. <a lay-event='delect' href="javascript:void(0)">
  160. <i class="fa fa-trash"></i> 删除直播
  161. </a>
  162. </li>
  163. </ul>
  164. </script>
  165. </div>
  166. </div>
  167. </div>
  168. </div>
  169. </div>
  170. </div>
  171. </div>
  172. <div class="go-live">
  173. <div class="live-box">
  174. <div class="live-title">
  175. <h2>直播推流地址</h2>
  176. </div>
  177. <div class="live-text">
  178. <label>服务器</label>
  179. <p id="live-href"></p>
  180. <button type="button" class="layui-btn layui-btn-normal copy" data-id="live-href">复制</button>
  181. </div>
  182. <div class="live-text">
  183. <label>串流密钥</label>
  184. <p id="live-code"></p>
  185. <button type="button" class="layui-btn layui-btn-normal copy" data-id="live-code">复制</button>
  186. </div>
  187. </div>
  188. </div>
  189. <div class="move_live_admin" hidden>
  190. <div style="padding: 20px; background-color: #F2F2F2;">
  191. <div class="layui-row layui-col-space15">
  192. <div class="layui-col-md12">
  193. <div class="layui-card">
  194. <div class="layui-card-body">
  195. <form class="layui-form" action="" lay-filter="admin_lists">
  196. <div class="layui-form-item">
  197. <label class="layui-form-label">管理用户:</label>
  198. <div class="layui-input-block">
  199. <select name="admin_id" lay-filter="admin_id" id="admin_id">
  200. <option value="">全部</option>
  201. {volist name='admin_list' id='item'}
  202. <option value="{$item.admin_id}">{$item.admin_name}</option>
  203. {/volist}
  204. </select>
  205. </div>
  206. </div>
  207. </form>
  208. </div>
  209. </div>
  210. </div>
  211. </div>
  212. </div>
  213. </div>
  214. <script src="{__ADMIN_PATH}js/layuiList.js"></script>
  215. {/block}
  216. {block name="script"}
  217. <script>
  218. //实例化form
  219. layList.form.render();
  220. layList.date({
  221. elem: '#datetime',
  222. theme: '#0092DC',
  223. type: 'datetime',
  224. range: '~'
  225. });
  226. //加载列表
  227. layList.tableList({o:'List', done:function () {}},"{:Url('special_list',['subject_id'=>$subject_id, 'special_type'=>$special_type])}",function (){
  228. return [
  229. {field: 'id', title: '编号', width:60,align: 'center'},
  230. {field: 'title', title: '直播标题',align: 'center'},
  231. {field: 'subject_name', title: '分类',align: 'center',width:75},
  232. {field: 'admin_name', title: '账号',align: 'center',width:85},
  233. {field: 'image', title: '封面',templet:'#image',align: 'center'},
  234. {field: 'recommend', title: '推荐',templet:'#recommend',align: 'center'},
  235. {field: 'browse_count', title: '浏览量',align: 'center',width:60},
  236. {field: 'stream_name', title: '直播间ID',align: 'center',width:75},
  237. {field: 'money', title: '价格',align: 'center',width:65},
  238. {field: 'member_money', title: '会员价',align: 'center',width:65},
  239. {field: 'pink_money', title: '拼团价',align: 'center',width:65},
  240. // {field: 'online_num', title: '虚拟在线人数',edit:'online_num',width:"5%",align: 'center'},
  241. {field: 'is_pink', title: '拼团状态',templet:'#is_pink',align: 'center',width:70},
  242. {field: 'sort', title: '排序',sort: true,event:'sort',edit:'sort',align: 'center',width:60},
  243. {field: 'is_show', title: '状态',templet:'#is_show',align: 'center',width:80},
  244. {field: 'right', title: '操作',align:'center',toolbar:'#act',width:70},
  245. ];
  246. });
  247. //下拉框
  248. $(document).click(function (e) {
  249. $('.layui-nav-child').hide();
  250. })
  251. $(function () {
  252. $(document).on('mouseover', '.recom-item', function () {
  253. var that = this;
  254. layui.use('layer', function () {
  255. var layer = layui.layer;
  256. layer.tips('点击即可取消此推荐', that, {
  257. tips: [1, '#0093dd']
  258. });
  259. });
  260. });
  261. $(document).on('mouseout', '.recom-item', function () {
  262. var that = this;
  263. layui.use('layer', function () {
  264. var layer = layui.layer;
  265. layer.closeAll();
  266. });
  267. });
  268. $(document).on('click', '.recom-item', function () {
  269. var that = this;
  270. var url = layList.U({ a: '../special.special_type/cancel_recommendation', q: { id: that.dataset.id, special_id: that.dataset.pid } });
  271. $eb.$swal(
  272. 'delete',
  273. function () {
  274. $eb.axios
  275. .get(url)
  276. .then(function (res) {
  277. if (res.data.code == 200) {
  278. $eb.$swal('success', res.data.msg);
  279. window.location.reload();
  280. } else {
  281. return Promise.reject(res.data.msg || '删除失败');
  282. }
  283. })
  284. .catch(function (err) {
  285. $eb.$swal('error', err);
  286. });
  287. },
  288. {
  289. title: '确定取消此推荐?',
  290. text: '取消后无法撤销,请谨慎操作!',
  291. confirm: '确定取消'
  292. }
  293. );
  294. });
  295. });
  296. function dropdown(that){
  297. var oEvent = arguments.callee.caller.arguments[0] || event;
  298. oEvent.stopPropagation();
  299. var offset = $(that).offset();
  300. var top=offset.top-$(window).scrollTop();
  301. var index = $(that).parents('tr').data('index');
  302. $('.layui-nav-child').each(function (key) {
  303. if (key != index) {
  304. $(this).hide();
  305. }
  306. })
  307. if($(document).height() < top+$(that).next('ul').height()){
  308. $(that).next('ul').css({
  309. 'padding': 10,
  310. 'top': - ($(that).parent('td').height() / 2 + $(that).height() + $(that).next('ul').height()/2),
  311. 'min-width': 'inherit',
  312. 'position': 'absolute'
  313. }).toggle();
  314. }else{
  315. $(that).next('ul').css({
  316. 'padding': 10,
  317. 'top':$(that).parent('td').height() / 2 + $(that).height(),
  318. 'min-width': 'inherit',
  319. 'position': 'absolute'
  320. }).toggle();
  321. }
  322. }
  323. //自定义方法
  324. var action= {
  325. set_value: function (field, id, value, model_type) {
  326. layList.baseGet(layList.Url({
  327. c: 'special.special_type' ,
  328. a: 'set_value',
  329. q: {field: field, id: id, value: value, model_type:model_type}
  330. }), function (res) {
  331. layList.msg(res.msg);
  332. });
  333. },
  334. //打开新添加页面
  335. open_add: function (url,title) {
  336. layer.open({
  337. type: 2 //Page层类型
  338. ,area: ['100%', '100%']
  339. ,title: title
  340. ,shade: 0.6 //遮罩透明度
  341. ,maxmin: true //允许全屏最小化
  342. ,anim: 1 //0-6的动画形式,-1不开启
  343. ,content: url
  344. ,end:function() {
  345. location.reload();
  346. }
  347. });
  348. },
  349. //直播间转移
  350. move_live_admin: function(data){
  351. layer.open({
  352. type: 1
  353. ,scrollbar: true
  354. ,area: ['500px', '70%']
  355. ,content: $('.move_live_admin')
  356. ,btn: '转让'
  357. ,btnAlign: 'c' //按钮居中
  358. ,shade: 0 //不显示遮罩
  359. ,yes: function(){
  360. var admin_id = $("#admin_id").val();
  361. if (!admin_id) {
  362. layer.msg("请选择转让账号", {
  363. icon: 2,
  364. time: 2000
  365. });
  366. return false;
  367. }
  368. layList.baseGet(layList.U({a:'move_live_admin',q:{special_id:data.id, admin_id:admin_id}}),function(res){
  369. if (res.code == 200) {
  370. layer.closeAll();
  371. layer.msg("转让成功", {
  372. icon: 1,
  373. time: 2000
  374. });
  375. }else{
  376. layer.closeAll();
  377. layer.msg("转让失败", {
  378. icon: 2,
  379. time: 2000
  380. });
  381. }
  382. }, function (res) {
  383. layer.msg(res.msg, {
  384. icon: 2,
  385. time: 2000
  386. });
  387. })
  388. }
  389. ,cancel:function () {
  390. $('.live_remind').hide();
  391. }
  392. });
  393. }
  394. }
  395. $('.copy').each(function () {
  396. $(this).on('click',function () {
  397. copy($(this).data('id'),function () {
  398. layList.msg('复制成功');
  399. });
  400. });
  401. })
  402. function copy (id, attr,errorFn)
  403. {
  404. var target = null,successFn=null;
  405. if(typeof attr=='function'){
  406. successFn=attr;
  407. attr='';
  408. }
  409. if (attr && typeof attr=='string') {
  410. target = document.createElement('div');
  411. target.id = 'tempTarget';
  412. target.style.opacity = '0';
  413. if (id) {
  414. var curNode = document.querySelector('#' + id);
  415. target.innerText = curNode[attr];
  416. } else {
  417. target.innerText = attr;
  418. }
  419. document.body.appendChild(target);
  420. } else {
  421. target = document.querySelector('#' + id);
  422. }
  423. try {
  424. var range = document.createRange();
  425. range.selectNode(target);
  426. window.getSelection().removeAllRanges();
  427. window.getSelection().addRange(range);
  428. document.execCommand('copy');
  429. window.getSelection().removeAllRanges();
  430. successFn && successFn();
  431. } catch (e) {
  432. errorFn && errorFn();
  433. }
  434. if (attr) {
  435. target.parentElement.removeChild(target);
  436. }
  437. }
  438. //查询
  439. layList.search('search',function(where){
  440. var arr_time = [];
  441. var start_time = '';
  442. var end_time = '';
  443. if (where.datetime) {
  444. arr_time = where.datetime.split('~');
  445. start_time = arr_time[0].trim();
  446. end_time = arr_time[1].trim();
  447. }
  448. layList.reload({
  449. activity_type: where.activity_type,
  450. subject_id: where.subject_id,
  451. is_show: where.is_show,
  452. start_time: start_time,
  453. end_time: end_time,
  454. store_name: where.store_name
  455. },true);
  456. });
  457. layList.switch('is_show',function (odj,value) {
  458. var is_show_value = 0
  459. if(odj.elem.checked==true){
  460. var is_show_value = 1
  461. }
  462. action.set_value('is_show',value,is_show_value,'special');
  463. });
  464. //快速编辑
  465. layList.edit(function (obj) {
  466. var id=obj.data.id,value=obj.value;
  467. switch (obj.field) {
  468. case 'title':
  469. action.set_value('title',id,value,'special');
  470. break;
  471. case 'sort':
  472. if(value < 0) return layList.msg('排序不能小于0');
  473. action.set_value('sort',id,value,'special');
  474. break;
  475. case 'online_num':
  476. layList.baseGet(layList.Url({
  477. c: 'live.aliyun_live' ,
  478. a: 'set_value',
  479. q: {stream_name: obj.data.stream_name,field:'online_num',value: value}
  480. }), function (res) {
  481. layList.msg(res.msg);
  482. });
  483. break;
  484. }
  485. });
  486. //监听并执行排序
  487. layList.sort(['id','sort'],true);
  488. //点击事件绑定
  489. layList.tool(function (event,data,obj) {
  490. switch (event) {
  491. case 'delect':
  492. var url=layList.U({a:'delete',q:{id:data.id}});
  493. $eb.$swal('delete',function(){
  494. $eb.axios.get(url).then(function(res){
  495. if(res.status == 200 && res.data.code == 200) {
  496. $eb.$swal('success','删除成功!');
  497. obj.del();
  498. }else
  499. return Promise.reject(res.data.msg || '删除失败')
  500. }).catch(function(err){
  501. $eb.$swal('error',err);
  502. });
  503. })
  504. break;
  505. case 'recommend':
  506. var url=layList.U({a:'recommend',q:{id:data.id}});
  507. $eb.$swal('delete',function(){
  508. $eb.axios.get(url).then(function(res){
  509. if(res.status == 200 && res.data.code == 200) {
  510. $eb.$swal('success',res.data.msg);
  511. obj.update({is_publish:1});
  512. }else
  513. return Promise.reject(res.data.msg || '删除失败')
  514. }).catch(function(err){
  515. $eb.$swal('error',err);
  516. });
  517. },{title:"确认要把该直播专题推荐到首页弹窗吗?",text:'确认后无法修改',confirm:'确认'});
  518. break;
  519. case 'open_image':
  520. $eb.openImage(data.image);
  521. break;
  522. case 'go_live':
  523. layList.baseGet(layList.U({a:'go_live',q:{id:data.id}}),function(res){
  524. $('#live-href').text(res.data.href);
  525. $('#live-code').text(res.data.code);
  526. layList.layer.open({
  527. type: 1,
  528. area: ['800px', 'auto'], //宽高
  529. content:$('.go-live'),
  530. title:false,
  531. cancel:function () {
  532. $('.go-live').hide();
  533. }
  534. });
  535. },function (res) {
  536. layList.msg(res.msg);
  537. });
  538. break;
  539. case 'move_live_admin':
  540. action.move_live_admin(data);
  541. }
  542. })
  543. </script>
  544. {/block}