playback.vue 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. <template>
  2. <app-layout>
  3. <view class="box">
  4. <video class="video"
  5. :src="videoUrl"
  6. :autoplay="true"
  7. object-fit="fill"
  8. :show-fullscreen-btn="false">
  9. </video>
  10. <view class="bottom-box">
  11. <view class="video-info-box">
  12. <view class="title">{{roomInfo.name}}</view>
  13. <view class="user-info">
  14. <image mode="aspectFill" class="anchor-img" :src="roomInfo.anchor_img"></image>
  15. <span class="anchor-name">{{roomInfo.anchor_name}}</span>
  16. </view>
  17. <view class="video-box">
  18. <view class="item"
  19. v-for="(video, index) in videoList"
  20. :key="index"
  21. v-if="index < 3"
  22. :class="{'item-active': index === currentIndex}"
  23. @click="itemClick(index, video)">
  24. 第{{index + 1}}部分
  25. </view>
  26. <view class="more-box" v-if="videoList.length > 3" @click='moreClick'>
  27. <span class="text">更多</span>
  28. <image class="icon" src="/static/image/icon/arrow-left-white.png"></image>
  29. </view>
  30. </view>
  31. </view>
  32. </view>
  33. </view>
  34. <view class="select-box" :class="{'select-box-show': isShowMore === 1, 'select-box-hidden': isShowMore === 2}">
  35. <image @click="isShowMore = 2" class="close" src="/static/image/icon/icon-close.png"></image>
  36. <view class="back-title">回放选集</view>
  37. <view class="video-list">
  38. <view v-for="(video, index) in videoList"
  39. :key="index"
  40. @click="itemClick(index, video)"
  41. :class="{'video-item-active': index === currentIndex}"
  42. class="video-item">
  43. 第{{index + 1}}部分
  44. </view>
  45. </view>
  46. </view>
  47. </app-layout>
  48. </template>
  49. <script>
  50. export default {
  51. data() {
  52. return {
  53. videoList: [],
  54. roomInfo: {},
  55. videoUrl: '',
  56. currentIndex: 0,
  57. isShowMore: 0,
  58. }
  59. },
  60. methods: {
  61. getPlayBack() {
  62. let self = this;
  63. self.$showLoading({
  64. text: '加载中...'
  65. });
  66. self.$request({
  67. url: self.$api.live.playback,
  68. data: {
  69. page: 1,
  70. room_id: self.roomInfo.id,
  71. },
  72. }).then(response => {
  73. self.$hideLoading();
  74. if (response.code === 0) {
  75. self.videoList = response.data.list;
  76. if (self.videoList.length > 0) {
  77. self.videoUrl = self.videoList[0].media_url;
  78. }
  79. if (self.videoList.length === 0) {
  80. uni.showModal({
  81. content: '该直播间没有回放数据',
  82. showCancel: false,
  83. confirmText: '我知道了',
  84. success: function (res) {
  85. uni.navigateBack();
  86. }
  87. })
  88. }
  89. } else {
  90. uni.showToast({
  91. title: response.msg,
  92. icon: 'none',
  93. duration: 1000,
  94. });
  95. }
  96. }).catch(() => {
  97. self.$hideLoading();
  98. });
  99. },
  100. itemClick(index, video) {
  101. this.currentIndex = index;
  102. this.videoUrl = video.media_url;
  103. },
  104. moreClick() {
  105. if (this.isShowMore === 0 || this.isShowMore === 2) {
  106. this.isShowMore = 1;
  107. } else {
  108. this.isShowMore = 2;
  109. }
  110. },
  111. },
  112. onLoad(options) {
  113. let self = this;
  114. uni.getStorage({
  115. key: 'live_playback',
  116. success(res) {
  117. self.roomInfo.name = res.data.room_info.name;
  118. self.roomInfo.anchor_name = res.data.room_info.anchor_name;
  119. self.roomInfo.anchor_img = res.data.room_info.anchor_img;
  120. }
  121. });
  122. this.roomInfo.id = options.room_id;
  123. this.getPlayBack();
  124. }
  125. }
  126. </script>
  127. <style scoped lang="scss">
  128. .box {
  129. width: 100%;
  130. height: 100vh;
  131. .video {
  132. width: 100%;
  133. height: 100%;
  134. }
  135. .bottom-box {
  136. position: fixed;
  137. bottom: 0;
  138. width: 100%;
  139. height: 320#{rpx};
  140. color: #fff;
  141. padding: 40#{rpx};
  142. font-size: 28#{rpx};
  143. background-image: linear-gradient(rgba(255, 255, 255, 0), rgba(0, 0, 0, 0.7));
  144. padding-bottom: 100#{rpx};
  145. pointer-events: none;
  146. .video-info-box {
  147. pointer-events: auto;
  148. }
  149. .title {
  150. font-size: 36#{rpx};
  151. font-weight: 900;
  152. width: 670#{rpx};
  153. overflow: hidden;
  154. text-overflow: ellipsis;
  155. white-space:nowrap;
  156. }
  157. .user-info {
  158. display: flex;
  159. margin-top: 20#{rpx};
  160. margin-bottom: 28#{rpx};
  161. .anchor-img {
  162. width: 40#{rpx};
  163. height: 40#{rpx};
  164. border-radius: 50%;
  165. }
  166. .anchor-name {
  167. margin-left: 20#{rpx};
  168. height: 40#{rpx};
  169. line-height: 40#{rpx};
  170. width: 600#{rpx};
  171. overflow: hidden;
  172. text-overflow: ellipsis;
  173. white-space:nowrap;
  174. }
  175. }
  176. .video-box {
  177. display: flex;
  178. /*justify-content: center;*/
  179. align-items: center;
  180. > view {
  181. /*flex-grow: 1;*/
  182. }
  183. .item {
  184. border: 1#{rpx} solid #fff;
  185. border-radius: 50#{rpx};
  186. margin-right: 10#{rpx};
  187. height: 56#{rpx};
  188. line-height: 56#{rpx};
  189. text-align: center;
  190. width: 150#{rpx};
  191. }
  192. .item-active {
  193. background: #fff;
  194. color: #000;
  195. }
  196. .more-box {
  197. display: flex;
  198. justify-content: center;
  199. align-items: center;
  200. margin-left: 60#{rpx};
  201. .icon {
  202. margin-left: 20#{rpx};
  203. width: 12#{rpx};
  204. height: 24#{rpx};
  205. transform: rotate(-90deg);
  206. }
  207. }
  208. }
  209. }
  210. }
  211. .select-box {
  212. width: 100%;
  213. height: 360#{rpx};
  214. background: #fff;
  215. border-top-left-radius: 16#{rpx};
  216. border-top-right-radius: 16#{rpx};
  217. padding: 0 40#{rpx};
  218. position: fixed;
  219. bottom: -360#{rpx};
  220. .close {
  221. width: 30#{rpx};
  222. height: 30#{rpx};
  223. position: absolute;
  224. right: 32#{rpx};
  225. top: 32#{rpx};
  226. }
  227. .back-title {
  228. width: 100%;
  229. margin: 44#{rpx} 0;
  230. font-size: 36#{rpx};
  231. text-align: center;
  232. }
  233. .video-list {
  234. display: flex;
  235. flex-wrap: wrap;
  236. height: 200#{rpx};
  237. overflow-y: auto;
  238. .video-item {
  239. width: 150#{rpx};
  240. height: #{56rpx};
  241. line-height: #{56rpx};
  242. text-align: center;
  243. margin-right: 15#{rpx};
  244. margin-bottom: 15#{rpx};
  245. font-size: 26#{rpx};
  246. color: #666666;
  247. -webkit-border-radius: 38#{rpx};
  248. -moz-border-radius: 38#{rpx};
  249. border-radius: 38#{rpx};
  250. border: 1#{rpx} solid #bbbbbb;
  251. }
  252. .video-item-active {
  253. color: #ffffff;
  254. border: none;
  255. background: #ff4544;
  256. }
  257. }
  258. }
  259. .select-box-show {
  260. -webkit-animation: selectShow 0.5s forwards;
  261. -o-animation: selectShow 0.5s forwards;
  262. animation: selectShow 0.5s forwards;
  263. }
  264. .select-box-hidden {
  265. -webkit-animation: selectHidden 0.5s forwards;
  266. -o-animation: selectHidden 0.5s forwards;
  267. animation: selectHidden 0.5s forwards;
  268. }
  269. @keyframes selectShow {
  270. from {
  271. bottom: -360#{rpx};
  272. }
  273. to {
  274. bottom: 0;
  275. }
  276. }
  277. @keyframes selectHidden {
  278. from {
  279. bottom: 0;
  280. }
  281. to {
  282. bottom: -360#{rpx};
  283. }
  284. }
  285. </style>