main-content.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  1. <template>
  2. <view>
  3. <title-header />
  4. <live-pusher :url="liveApplyInfo?liveApplyInfo.live_apply_push_url:''" mode="HD" id="camera-push" :beauty="beauty"
  5. enable-camera="true" @statechange="statechange" @error="liveError" device-position="back"
  6. waiting-image="@/static/image/live/video.png" style="top:0;bottom:0;right:0;left:0;position:fixed">
  7. </live-pusher>
  8. <cover-view style="top:0;bottom:0;right:0;left:0;position:fixed">
  9. <cover-view class="live-header">
  10. <cover-view class="live-header-content">
  11. <cover-image class="live-avatar live-header-avatar" v-if="liveApplyInfo"
  12. :src="liveApplyInfo.live_apply_image"></cover-image>
  13. <cover-view class="live-header-info">
  14. <cover-view><text class="course-name" v-if="liveApplyInfo">{{liveApplyInfo.live_apply_name}}</text></cover-view>
  15. <cover-view><text class="course-online-count" v-if="onlineInfo">在线人数:{{onlineInfo.online_count}}</text></cover-view>
  16. </cover-view>
  17. </cover-view>
  18. <cover-view class="live-header-right">
  19. <cover-image v-if="openLive && !closeLive" class="live-header-icon" src="@/static/image/live/close.png"
  20. @click='goCloseLive'></cover-image>
  21. </cover-view>
  22. </cover-view>
  23. <cover-view class="live-online-list" v-if="onlineInfo">
  24. <cover-view class="live-online-avatar" v-for="(item,index) in onlineInfo.online_list" :key="index">
  25. <cover-image v-if="item.instant_message_from_avatar" class="live-avatar"
  26. :src="item.instant_message_from_avatar"></cover-image>
  27. </cover-view>
  28. </cover-view>
  29. <cover-view><text v-if="closeLive" class='close-live-text'>您已退出直播间</text></cover-view>
  30. <cover-view><text v-if="!openLive" class='close-live-text'>未找到直播</text></cover-view>
  31. <cover-view><text v-if="openLive && !buttonOn" @click="createContext" class='on-live-text'>点击开始直播</text></cover-view>
  32. <cover-view class="live-bottom">
  33. <cover-view class="chat-message-list" v-if="chatList && showChat">
  34. <cover-view class="chat-message-item-wrapper" v-for="(item,index) in chatList" :key="index">
  35. <cover-view class="chat-message-item">
  36. <text class="chat-user-name">{{item.instant_message_from_name}}:</text>
  37. <text class="chat-message-text">{{item.instant_message}}</text>
  38. </cover-view>
  39. <cover-view class="line-content"></cover-view>
  40. </cover-view>
  41. </cover-view>
  42. <cover-view v-if="hasgift" class="gift-wrapper">
  43. <cover-view class="gift-ani">
  44. <cover-image :src="giftAvatar" class="avatar" />
  45. <cover-view class="info-name">
  46. <cover-view><text class="nick">{{giftNick}}</text></cover-view>
  47. <cover-view><text class="gift">送出 火箭</text></cover-view>
  48. </cover-view>
  49. </cover-view>
  50. <cover-image src="@/static/image/live/gift-item.png" class="gitf-item" />
  51. </cover-view>
  52. <cover-view class="cover-input-wrapper">
  53. <cover-view v-if="buttonOn" class="cover-btn-wrapper">
  54. <cover-image class="cover-btn-icon icon-barrage" src="@/static/image/live/beauty.png" @click="goBeauty">
  55. </cover-image>
  56. </cover-view>
  57. <cover-view class="cover-btn-wrapper">
  58. <cover-image class="cover-btn-icon icon-barrage" src="@/static/image/live/setting.png" @click="goSetting">
  59. </cover-image>
  60. </cover-view>
  61. <cover-view v-if="openLive" class="cover-btn-wrapper">
  62. <cover-image class="cover-btn-icon icon-barrage" src="@/static/image/live/refresh.png" @click="goFresh">
  63. </cover-image>
  64. </cover-view>
  65. <cover-view v-if="buttonOn" class="cover-btn-wrapper">
  66. <cover-image v-if="showChat" class="cover-btn-icon icon-barrage" src="@/static/image/live/barrage-off.png"
  67. @click="toggleChat"></cover-image>
  68. <cover-image v-else class="cover-btn-icon icon-barrage" src="@/static/image/live/barrage-on.png"
  69. @click="toggleChat"></cover-image>
  70. </cover-view>
  71. <cover-view v-if="buttonOn" class="cover-btn-wrapper">
  72. <cover-image class="cover-btn-icon icon-barrage" src="@/static/image/live/camera.png" @click="toggleCamera">
  73. </cover-image>
  74. </cover-view>
  75. </cover-view>
  76. </cover-view>
  77. </cover-view>
  78. <uni-popup background-color="#fff" ref="confirm" type="dialog">
  79. <uni-popup-dialog :mode="dialog.mode" :title="dialog.title" :content="dialog.content"
  80. :placeholder="dialog.content" @confirm="confirmDialog" @close="closeDialog"></uni-popup-dialog>
  81. </uni-popup>
  82. </view>
  83. </template>
  84. <script>
  85. import {
  86. mapState,
  87. mapActions
  88. } from 'vuex'
  89. import {
  90. getLiveApplyInfo,
  91. leaveLiveApply,
  92. changeLiveApply,
  93. joinLiveApply
  94. } from '../../../../api/sellerLiveApply'
  95. import {
  96. addInstantMessage
  97. } from '../../../../api/sellerInstantMessage'
  98. import TitleHeader from '../../../TitleHeader'
  99. export default {
  100. data() {
  101. return {
  102. canReconnect:true,
  103. dialog:{},
  104. beauty: 0,
  105. ifAuthRecord: false,
  106. ifAuthCamera: false,
  107. liveApplyInfo: false,
  108. onlineInfo: {
  109. online_count: 0,
  110. online_list: {}
  111. },
  112. chatList: {},
  113. showChat: true,
  114. ifConnect: false,
  115. clientId: false,
  116. openLive: false,
  117. closeLive: false,
  118. lockReconnect: false,
  119. timeOut: false,
  120. livePusher: {},
  121. buttonOn: false,
  122. hasgift: false,
  123. giftAvatar: '',
  124. giftNick: '',
  125. }
  126. },
  127. computed: {
  128. ...mapState({
  129. config: state => state.config.config,
  130. }),
  131. },
  132. components: {
  133. TitleHeader,
  134. },
  135. props: ['live_apply_id'],
  136. created() {
  137. this.fetchConfig({})
  138. if (!this.live_apply_id) {
  139. uni.showToast({
  140. icon: 'none',
  141. title: '参数错误'
  142. })
  143. }
  144. this.load()
  145. },
  146. mounted() {
  147. var livePusher = uni.createLivePusherContext('camera-push',this)
  148. this.livePusher = livePusher
  149. },
  150. beforeDestroy: function () {
  151. this.canReconnect=false
  152. heartCheck.stop()
  153. },
  154. methods: {
  155. ...mapActions({
  156. fetchConfig: 'fetchConfig'
  157. }),
  158. closeDialog() {},
  159. confirmDialog(value) {
  160. uni.showLoading({
  161. title: '请稍等',
  162. })
  163. leaveLiveApply({
  164. live_apply_push_message: value,
  165. live_apply_id: this.liveApplyInfo.live_apply_id,
  166. client_id: this.clientId
  167. }).then(res=>{
  168. if(this.livePusher){
  169. this.livePusher.stop()
  170. }
  171. this.closeLive = true
  172. uni.hideLoading()
  173. uni.navigateBack({delta:1})
  174. }).catch(res=>{
  175. console.log(res)
  176. uni.showToast({
  177. title: res.message,
  178. icon: 'none'
  179. });
  180. uni.hideLoading()
  181. })
  182. },
  183. load(){
  184. getLiveApplyInfo(this.live_apply_id).then(res => {
  185. var live_apply_info = res.result.live_apply_info
  186. if (live_apply_info.live_apply_state != 1) {
  187. uni.showToast({
  188. title: '直播未审核',
  189. icon: 'none'
  190. });
  191. return
  192. }
  193. if (!live_apply_info.live_apply_push_url) {
  194. uni.showToast({
  195. title: '未设置推流URL',
  196. icon: 'none'
  197. });
  198. return
  199. }
  200. if (!live_apply_info.live_apply_play_url) {
  201. uni.showToast({
  202. title: '未设置播放URL',
  203. icon: 'none'
  204. });
  205. return
  206. }
  207. var timestamp = new Date().getTime() / 1000
  208. if (live_apply_info.live_apply_end_time < timestamp) {
  209. uni.showToast({
  210. title: '直播已结束',
  211. icon: 'none'
  212. });
  213. return
  214. }
  215. if ((live_apply_info.live_apply_play_time - 3600) > timestamp) {
  216. uni.showToast({
  217. title: '只能提前一小时入场',
  218. icon: 'none'
  219. });
  220. return
  221. }
  222. //用户授权
  223. /*uni.getSetting({
  224. success(res) {
  225. if (!res.authSetting['scope.record']) {
  226. uni.authorize({
  227. scope: 'scope.record',
  228. success() {
  229. _this.ifAuthRecord = true
  230. },
  231. fail() {
  232. uni.showToast({
  233. title: '获取录音权限失败',
  234. icon: 'none'
  235. });
  236. }
  237. })
  238. } else {
  239. _this.ifAuthRecord = true
  240. }
  241. if (!res.authSetting['scope.camera']) {
  242. uni.authorize({
  243. scope: 'scope.camera',
  244. success() {
  245. _this.ifAuthCamera = true
  246. },
  247. fail() {
  248. uni.showToast({
  249. title: '获取摄像权限失败',
  250. icon: 'none'
  251. });
  252. }
  253. })
  254. } else {
  255. _this.ifAuthCamera = true
  256. }
  257. },
  258. fail(res) {
  259. uni.showToast({
  260. title: res.errMsg,
  261. icon: 'none'
  262. });
  263. }
  264. })*/
  265. this.liveApplyInfo = live_apply_info,
  266. this.onlineInfo = res.result.online_info,
  267. this.openLive = true
  268. if (live_apply_info.instant_message_url) {
  269. this.createWebSocket()
  270. }
  271. }).catch(error => {
  272. uni.showToast({
  273. icon: 'none',
  274. title: error.message
  275. })
  276. })
  277. },
  278. createContext() {
  279. /*if (!this.ifAuthCamera || !this.ifAuthRecord) {
  280. uni.showToast({
  281. title: '直播需要录音与摄像权限,请点击底部设置按钮开启后刷新',
  282. icon: 'none'
  283. });
  284. return
  285. }*/
  286. var _this = this
  287. this.buttonOn = true
  288. _this.livePusher.start({
  289. success: function(res) {
  290. changeLiveApply({
  291. live_apply_id: _this.liveApplyInfo.live_apply_id,
  292. live_apply_push_state: 1
  293. }).then(res=> {
  294. console.log(res)
  295. uni.showToast({
  296. title: res.message,
  297. icon: 'none'
  298. });
  299. }).catch(res=> {
  300. console.log(res)
  301. uni.showToast({
  302. title: res.message,
  303. icon: 'none'
  304. });
  305. })
  306. },
  307. fail: function(res) {
  308. console.log(res)
  309. }
  310. });
  311. },
  312. statechange(res) {
  313. console.log(res)
  314. },
  315. liveError(res) {
  316. console.log(res)
  317. uni.showToast({
  318. title: res.errMsg,
  319. icon: 'none'
  320. });
  321. },
  322. goBeauty() {
  323. this.beauty = (this.beauty + 1) % 10
  324. console.log(this.beauty)
  325. uni.showToast({
  326. title: '美颜' + (this.beauty + 1) * 10 + '%',
  327. icon: 'none'
  328. });
  329. },
  330. goFresh() {
  331. this.load()
  332. },
  333. goSetting() {
  334. uni.openSetting({
  335. fail(res) {
  336. uni.showToast({
  337. title: '操作失败',
  338. icon: 'none'
  339. });
  340. }
  341. })
  342. },
  343. toggleChat(e) {
  344. this.showChat = !this.showChat
  345. },
  346. sendMessage(e) {
  347. var _this = this
  348. if (!this.ifConnect) {
  349. uni.showToast({
  350. title: '未接入聊天系统',
  351. icon: 'none'
  352. });
  353. return;
  354. }
  355. if (!this.inputInfo) {
  356. uni.showToast({
  357. title: '请输入聊天内容',
  358. icon: 'none'
  359. });
  360. return;
  361. }
  362. uni.showLoading({
  363. title: '发送中',
  364. })
  365. addInstantMessage({
  366. to_id: this.liveApplyInfo.live_apply_id,
  367. to_type: 2,
  368. message: this.inputInfo,
  369. message_type: 0
  370. }).then(res=> {
  371. _this.inputFocus = false,
  372. _this.inputInfo = '',
  373. _this.inputModel = ''
  374. console.log(res)
  375. uni.showToast({
  376. title: res.message,
  377. icon: 'none'
  378. });
  379. }).catch(res=> {
  380. console.log(res)
  381. uni.showToast({
  382. title: res.message,
  383. icon: 'none'
  384. });
  385. })
  386. },
  387. goCloseLive() {
  388. this.dialog = {
  389. mode: 'input',
  390. title: '请输入关闭直播理由',
  391. }
  392. this.$refs.confirm.open()
  393. },
  394. createWebSocket() {
  395. try {
  396. uni.connectSocket({
  397. url: this.liveApplyInfo.instant_message_url,
  398. })
  399. this.initWebSocket();
  400. } catch (e) {
  401. this.reconnectWebSocket();
  402. }
  403. },
  404. initWebSocket() {
  405. var _this = this
  406. uni.onSocketClose(function(res) {
  407. _this.ifConnect = false,
  408. console.log(res)
  409. if (res.reason) {
  410. uni.showToast({
  411. title: '聊天系统连接断开:' + res.reason,
  412. icon: 'none'
  413. });
  414. }
  415. if(_this.canReconnect){
  416. _this.reconnectWebSocket();
  417. }
  418. })
  419. uni.onSocketError(function(res) {
  420. uni.showToast({
  421. title: '聊天系统接入失败:' + res.errMsg,
  422. icon: 'none'
  423. });
  424. _this.reconnectWebSocket();
  425. })
  426. uni.onSocketOpen(function(res) {
  427. _this.ifConnect = true,
  428. uni.showToast({
  429. title: '聊天系统接入成功',
  430. icon: 'none'
  431. });
  432. //心跳检测重置
  433. heartCheck.start();
  434. })
  435. uni.onSocketMessage(function(res) {
  436. console.log(res)
  437. var message = JSON.parse(res.data)
  438. if (!message) {
  439. uni.showToast({
  440. title: '消息转换失败:' + res,
  441. icon: 'none'
  442. });
  443. return
  444. }
  445. var type = message.type || '';
  446. switch (type) {
  447. // Events.php中返回的init类型的消息,将client_id发给后台进行uid绑定
  448. case 'init':
  449. _this.clientId = message.client_id
  450. //加入聊天
  451. joinLiveApply({
  452. live_apply_id: _this.liveApplyInfo.live_apply_id,
  453. client_id: message.client_id
  454. }).catch(res=> {
  455. console.log(res)
  456. uni.showToast({
  457. title: res.message,
  458. icon: 'none'
  459. });
  460. })
  461. break;
  462. case 'leave':
  463. //离开聊天
  464. var onlineInfo = {
  465. online_count: message.online_count,
  466. online_list: message.online_list
  467. }
  468. _this.onlineInfo = onlineInfo
  469. break;
  470. case 'join':
  471. var onlineInfo = {
  472. online_count: message.online_count,
  473. online_list: message.online_list
  474. }
  475. _this.onlineInfo = onlineInfo
  476. break;
  477. case 'gift':
  478. _this._this.hasgift = true
  479. _this.giftAvatar = message.member.member_avatar
  480. _this.giftNick = message.member.member_name
  481. console.log(message.member.member_avatar)
  482. setTimeout(() => {
  483. _this.hasgift = false
  484. _this.giftAvatar = ''
  485. _this.giftNick = ''
  486. }, 1000)
  487. break
  488. // 当mvc框架调用GatewayClient发消息时直接alert出来
  489. default:
  490. var chatList = _this.chatList
  491. if (!chatList) {
  492. chatList = {}
  493. }
  494. chatList[(Date.parse(new Date()) / 1000) + '' + Math.ceil(Math.random() * 10000)] = message
  495. _this.chatList = chatList
  496. console.log(chatList)
  497. }
  498. heartCheck.start();
  499. })
  500. },
  501. reconnectWebSocket() {
  502. var _this = this
  503. if (_this.lockReconnect) {
  504. return;
  505. };
  506. _this.lockReconnect = true
  507. //没连接上会一直重连,设置延迟避免请求过多
  508. _this.timeOut && clearTimeout(_this.timeOut);
  509. _this.timeOut = setTimeout(function() {
  510. _this.createWebSocket();
  511. _this.lockReconnect = false
  512. }, 4000)
  513. },
  514. toggleCamera() {
  515. this.livePusher.switchCamera()
  516. }
  517. }
  518. }
  519. //心跳检测
  520. var heartCheck = {
  521. timeout: 3000,
  522. timeoutObj: null,
  523. start: function() {
  524. var self = this;
  525. this.timeoutObj && clearInterval(this.timeoutObj);
  526. this.timeoutObj = setInterval(function() {
  527. //这里发送一个心跳,后端收到后,返回一个心跳消息,
  528. uni.sendSocketMessage({
  529. data: "123456789"
  530. })
  531. }, this.timeout)
  532. },
  533. stop:function(){
  534. this.timeoutObj && clearInterval(this.timeoutObj)
  535. }
  536. }
  537. </script>
  538. <style lang="scss" scoped>
  539. .message-box-wrapper {
  540. position: fixed;
  541. top: 0;
  542. bottom: 0;
  543. left: 0;
  544. right: 0;
  545. background: rgba(0, 0, 0, 0.5);
  546. z-index: 10
  547. }
  548. .message-box {
  549. background: #fff;
  550. border-radius: 20rpx;
  551. padding: 40rpx;
  552. width: 80%;
  553. /* #ifndef APP-PLUS-NVUE */
  554. margin: 0 auto;
  555. /* #endif */
  556. position: relative;
  557. top: 50%;
  558. margin-top: -120rpx;
  559. }
  560. .message-box-content {
  561. border: 1px solid #eee;
  562. padding: 10rpx;
  563. position: relative
  564. }
  565. .message-box-titile {
  566. margin-bottom: 20rpx;
  567. color: #999
  568. }
  569. .message-box-text {
  570. height: 100rpx;
  571. border-radius: 10rpx;
  572. }
  573. .message-box-input {
  574. height: 100rpx;
  575. position: absolute;
  576. left: 10rpx;
  577. top: 10rpx;
  578. z-index: 2
  579. }
  580. .message-box-btn {
  581. /* #ifndef APP-PLUS-NVUE */
  582. display: flex;
  583. /* #endif */
  584. margin-top: 20rpx;
  585. }
  586. .message-box-btn-item {
  587. flex: 1
  588. }
  589. .message-box-btn-item:first-child {
  590. margin-right: 10rpx;
  591. }
  592. .message-box-btn-item:last-child {
  593. margin-left: 10rpx;
  594. }
  595. .live-header {
  596. /* #ifndef APP-PLUS-NVUE */
  597. display: flex;
  598. /* #endif */
  599. margin-top: 60rpx;
  600. flex-direction: row;
  601. }
  602. .live-header-content {
  603. flex: 1;
  604. /* #ifndef APP-PLUS-NVUE */
  605. display: flex;
  606. /* #endif */
  607. flex-direction: row;
  608. position: relative;
  609. left: -70rpx;
  610. align-items: center;
  611. background: rgba(0, 0, 0, 0.5);
  612. padding-right: 50rpx;
  613. border-radius: 70rpx;
  614. padding-top: 20rpx;
  615. padding-bottom: 20rpx;
  616. padding-left: 90rpx;
  617. }
  618. .live-header-info {
  619. flex: 1;
  620. padding-left: 20rpx;
  621. }
  622. .live-header-right {
  623. padding-right: 20rpx;
  624. width: 100rpx;
  625. }
  626. .live-header-icon {
  627. width: 50rpx;
  628. height: 50rpx;
  629. /* #ifndef APP-PLUS-NVUE */
  630. float: right;
  631. /* #endif */
  632. }
  633. .live-avatar {
  634. width: 100rpx;
  635. height: 100rpx;
  636. border-radius: 50%;
  637. border: 1px solid #fff;
  638. }
  639. .close-live-text {
  640. text-align: center;
  641. margin-top: 20rpx;
  642. color: #fff;
  643. }
  644. .on-live-text {
  645. text-align: center;
  646. margin-top: 20rpx;
  647. color: #26a2ff;
  648. }
  649. .course-name {
  650. /* #ifndef APP-PLUS-NVUE */
  651. white-space: nowrap;
  652. /* #endif */
  653. text-overflow: ellipsis;
  654. overflow: hidden;
  655. color: #fff;
  656. font-size: 30rpx;
  657. }
  658. .course-online-count {
  659. color: #eee;
  660. margin-top: 10rpx;
  661. font-size: 26rpx;
  662. }
  663. .live-online-list {
  664. flex-direction: row;
  665. align-items: center;
  666. padding: 10rpx;
  667. height: 120rpx;
  668. }
  669. .live-online-avatar {
  670. margin: 0 10rpx;
  671. }
  672. .chat-message-list {
  673. padding: 20rpx;
  674. position: absolute;
  675. bottom: 100rpx;
  676. left: 0;
  677. right: 0;
  678. }
  679. .chat-message-item-wrapper{
  680. /* #ifndef APP-PLUS-NVUE */
  681. display: flex;
  682. /* #endif */
  683. flex-direction: row;
  684. }
  685. .line-content{flex:1}
  686. .chat-message-item {
  687. /* opacity: 0.8; */
  688. padding: 10rpx 20rpx;
  689. background: rgba(0, 0, 0, 0.5);
  690. font-size: 26rpx;
  691. /* #ifndef APP-PLUS-NVUE */
  692. display: flex;
  693. /* #endif */
  694. flex-direction: row;
  695. margin-bottom: 20rpx;
  696. border-radius: 26rpx;
  697. }
  698. .chat-user-name {
  699. padding-right: 10rpx;
  700. color: #19a1fd;
  701. }
  702. .chat-message-text {
  703. flex: 1;
  704. color: #fff;
  705. /* #ifndef APP-PLUS-NVUE */
  706. display: inline;
  707. white-space: normal;
  708. word-wrap: break-word;
  709. word-break: break-all;
  710. /* #endif */
  711. }
  712. .cover-input-wrapper {
  713. /* #ifndef APP-PLUS-NVUE */
  714. display: flex;
  715. /* #endif */
  716. flex-direction: row;
  717. padding: 20rpx;
  718. /* opacity: 0.8; */
  719. align-items: center;
  720. justify-content: flex-end;
  721. position: absolute;
  722. bottom: 0;
  723. left: 0;
  724. right: 0;
  725. }
  726. .cover-input {
  727. flex: 1;
  728. height: 80rpx;
  729. line-height: 80rpx;
  730. border-radius: 40rpx;
  731. background-color: rgba(0, 0, 0, 0.5);
  732. position: relative;
  733. padding-left: 20rpx;
  734. padding-right: 20rpx;
  735. color: #fff;
  736. }
  737. .cover-input-text {
  738. height: 80rpx;
  739. line-height: 80rpx;
  740. }
  741. .cover-input-input {
  742. height: 80rpx;
  743. line-height: 80rpx;
  744. /* margin-top为text的高度,保持视觉上一致 */
  745. margin-top: -80rpx;
  746. }
  747. .cover-btn-wrapper {
  748. padding-left: 20rpx;
  749. }
  750. .cover-btn {
  751. width: 60rpx;
  752. height: 60rpx;
  753. border-radius: 60rpx;
  754. background-color: rgba(0, 0, 0, 0.5);
  755. }
  756. .icon-send {
  757. width: 40rpx;
  758. height: 40rpx;
  759. margin-top: 10rpx;
  760. margin-left: 10rpx;
  761. }
  762. .icon-barrage {
  763. width: 60rpx;
  764. height: 60rpx;
  765. }
  766. .live-bottom {
  767. position: absolute;
  768. bottom: 0;
  769. left:0;
  770. right:0;
  771. height: 600rpx;
  772. z-index: 2;
  773. overflow: hidden;
  774. }
  775. .gift-wrapper {
  776. position: relative;
  777. height: 170rpx;
  778. }
  779. .gift-ani {
  780. /* #ifndef APP-PLUS-NVUE */
  781. display: flex;
  782. /* #endif */
  783. flex-direction: row;
  784. background-color: rgba(0, 0, 0, 0.18);
  785. border-radius: 40rpx;
  786. width: 330rpx;
  787. height: 80rpx;
  788. position: relative;
  789. margin-top: 40rpx;
  790. }
  791. .avatar,
  792. .info-name {
  793. /* #ifndef APP-PLUS-NVUE */
  794. display: inline-block;
  795. vertical-align: middle
  796. /* #endif */
  797. }
  798. .avatar {
  799. height: 72rpx;
  800. width: 72rpx;
  801. border-radius: 36rpx;
  802. margin: 4rpx;
  803. }
  804. .nick {
  805. font-family: PingFangSC-Medium;
  806. font-size: 12px;
  807. color: #FFFFFF;
  808. /* #ifndef APP-PLUS-NVUE */
  809. letter-spacing: 0;
  810. /* #endif */
  811. text-align: left;
  812. line-height: 24rpx;
  813. }
  814. .gift {
  815. font-family: PingFangSC-Regular;
  816. font-size: 12px;
  817. color: #FFFFFF;
  818. /* #ifndef APP-PLUS-NVUE */
  819. letter-spacing: 0;
  820. /* #endif */
  821. text-align: left;
  822. line-height: 44rpx;
  823. }
  824. .gitf-item {
  825. height: 170rpx;
  826. width: 93rpx;
  827. position: absolute;
  828. left: 230rpx;
  829. top: 0;
  830. margin-top: 0rpx
  831. }
  832. </style>