Files
xdd-uniapp-new/pages/VideoPlayBackList/VideoPlayBackList.vue
T

278 lines
7.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view>
<view class="type-list flex ai-center">
<view class="item" :class="{'active':type===item.value}" v-for="(item,index) in typeList" :key="index"
@click="changeType(item)">{{ item.label }}
</view>
</view>
<view class="list" v-show="hasList">
<view class="video-waterfalls-wrap">
<view class="waterfalls-column">
<view class="item" v-for="(lItem,lIndex) in leftList" :key="lIndex" @click="goDetail(lItem)">
<image class="cover" :src="lItem.cover" mode="widthFix" lazy-load></image>
<view class="content">
<view class="title more-t">{{ lItem.title }}</view>
<view class="footer flex jc-between ai-center">
<view class="visit flex ai-center">
<image class="icon" style="margin-right: 8rpx" :src="lItem.storeLogo" mode="scaleToFill"></image>
{{ lItem.storeName }}
</view>
<image class="icon flex-0" :src="webUrl+'/20210806121203835373.png'" mode="scaleToFill"></image>
</view>
</view>
</view>
</view>
<view class="waterfalls-column">
<view class="item" v-for="(rItem,rIndex) in rightList" :key="rIndex" @click="goDetail(rItem)">
<image class="cover" :src="rItem.cover" mode="widthFix" lazy-load></image>
<view class="content">
<view class="title more-t">{{ rItem.title }}</view>
<view class="footer flex jc-between ai-center">
<view class="visit flex ai-center">
<image class="icon" style="margin-right: 8rpx" :src="rItem.storeLogo" mode="scaleToFill"></image>
{{ rItem.storeName }}
</view>
<image class="icon flex-0" :src="webUrl+'/20210806121203835373.png'" mode="scaleToFill"></image>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="loading-more" v-show="isWait">加载中...</view>
<view class="v4-nodata" v-show="showEmpty">
<image src="@/static/images/img_nodata.png" mode="scaleToFill"/>
<view class="text">暂无数据</view>
</view>
</view>
</template>
<script>
import {getStoreVideoType, getArticleList} from '@/api/public'
import {getVideoList} from '@/api/user'
import { pageListenMixins } from '@/mixins/pageListenMixins'
// 封面固定宽度(rpx
const COVER_WIDTH = 332
// 每项除封面外的文字内容预估高度(rpx)
const TEXT_HEIGHT = 120
export default {
mixins: [pageListenMixins],
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
typeList: [{'label': '全部', 'value': ''}],
type: '',
page: 1,
limit: 10,
keyword: '',
leftList: [],
rightList: [],
leftHeight: 0,
rightHeight: 0,
isWait: false,
requestId: 0,
pageKeyId: Object.freeze('findVideoList')
}
},
computed: {
hasList() {
return this.leftList.length + this.rightList.length > 0
},
showEmpty() {
return !this.isWait && !this.hasList
}
},
onLoad(options) {
if (!options.click) {
uni.switchTab({ url: '/pages/home/index' })
return
}
this.getType()
this.fetchList()
},
onReachBottom() {
this.page++
this.fetchList()
},
methods: {
getType() {
getStoreVideoType().then(({data}) => {
if (data.length > 0) {
data.forEach(item => {
this.typeList.push(item)
})
}
})
},
changeType(item) {
this.type = item.value
this.page = 1
// 使进行中的请求失效并解锁,避免切换时被上一次请求阻塞
this.requestId++
this.isWait = false
this.fetchList()
},
resetList() {
this.leftList = []
this.rightList = []
this.leftHeight = 0
this.rightHeight = 0
},
async fetchList() {
if (this.isWait) return
const requestId = ++this.requestId
this.isWait = true
const params = {
type: this.type,
page: this.page,
limit: this.limit
}
try {
const res = await getVideoList(params)
// 请求已被更新的请求(如切换分类)取代,丢弃本次结果
if (requestId !== this.requestId) return
if (res.status === 200) {
const items = res.data
for (let i = 0; i < items.length; i++) {
items[i].hide = true
}
// 并行获取所有封面高度,完成后一次性替换列表,避免闪现空列表
const heights = await Promise.all(items.map(item => this.getImageHeight(item.cover)))
if (requestId !== this.requestId) return
if (this.page === 1) this.resetList()
items.forEach((item, i) => {
this.pushToColumn(item, heights[i] + TEXT_HEIGHT)
})
}
} catch (e) {
// 忽略请求或图片尺寸获取失败
} finally {
if (requestId === this.requestId) {
this.isWait = false
}
}
},
getImageHeight(src) {
return new Promise(resolve => {
uni.getImageInfo({
src,
success: res => {
resolve(res.height / res.width * COVER_WIDTH)
},
fail: () => {
resolve(COVER_WIDTH)
}
})
})
},
pushToColumn(item, height) {
if (this.leftHeight <= this.rightHeight) {
this.leftList.push(item)
this.leftHeight += height
} else {
this.rightList.push(item)
this.rightHeight += height
}
},
goDetail(item) {
this.$yrouter.push("/pages/VideoPlayBackList/VideoPlayBackDetail?videoUrl=" + item.video + '&id=' + item.id + '&click=1')
}
}
}
</script>
<style lang="less">
.type-list {
margin: 28rpx 32rpx;
.item {
margin-right: 20rpx;
padding: 12rpx 16rpx;
border-radius: 20rpx;
background: #fff;
font-size: 26rpx;
white-space: nowrap;
}
.active {
background: #f66;
color: #fff;
}
}
.list {
margin: 28rpx 32rpx;
.video-waterfalls-wrap {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.waterfalls-column {
width: 332rpx;
}
.item {
margin-bottom: 20rpx;
border-radius: 4rpx;
background: #fff;
.cover {
width: 332rpx;
vertical-align: middle;
}
.title {
padding: 12rpx 16rpx;
font-size: 26rpx;
font-weight: bold;
line-height: 38rpx;
color: #333;
}
.mark {
margin: 14rpx 16rpx;
font-size: 22rpx;
line-height: 32rpx;
color: #999;
}
.footer {
padding: 12rpx 16rpx 16rpx;
border-top: 1rpx solid #E1E1E1;
font-size: 22rpx;
}
.icon {
width: 40rpx;
height: 40rpx;
vertical-align: middle;
border-radius: 50%;
}
.visit {
width: 100%;
color: #333;
overflow: hidden;
}
.time {
color: #999;
}
}
}
.loading-more {
padding: 24rpx 0;
text-align: center;
font-size: 24rpx;
color: #999;
}
</style>