|
|
<template>
|
|
|
<view class="waterfalls-box" :style="{ height: height + 'px' }">
|
|
|
<!-- #ifdef MP-WEIXIN -->
|
|
|
<view
|
|
|
v-for="(item, index) of list"
|
|
|
class="waterfalls-list"
|
|
|
:key="item[idKey]"
|
|
|
:id="'waterfalls-list-id-' + item[idKey]"
|
|
|
:ref="'waterfalls-list-id-' + item[idKey]"
|
|
|
:style="{
|
|
|
'--offset': offset + 'px',
|
|
|
'--cols': cols,
|
|
|
top: allPositionArr[index].top || 0,
|
|
|
left: allPositionArr[index].left || 0,
|
|
|
}"
|
|
|
@click="$emit('wapper-lick', item)"
|
|
|
>
|
|
|
<image
|
|
|
class="waterfalls-list-image"
|
|
|
mode="widthFix"
|
|
|
:class="{ single }"
|
|
|
:style="imageStyle"
|
|
|
:src="item[imageSrcKey] || ' '"
|
|
|
@load="imageLoadHandle(index)"
|
|
|
@error="imageLoadHandle(index)"
|
|
|
@click="$emit('image-click', item)"
|
|
|
/>
|
|
|
</view>
|
|
|
<!-- #endif -->
|
|
|
|
|
|
<!-- #ifndef MP-WEIXIN -->
|
|
|
<view
|
|
|
v-for="(item, index) of list"
|
|
|
class="waterfalls-list"
|
|
|
:key="item[idKey]"
|
|
|
:id="'waterfalls-list-id-' + item[idKey]"
|
|
|
:ref="'waterfalls-list-id-' + item[idKey]"
|
|
|
:style="{
|
|
|
'--offset': offset + 'px',
|
|
|
'--cols': cols,
|
|
|
...listStyle,
|
|
|
...(allPositionArr[index] || {}),
|
|
|
}"
|
|
|
@click="$emit('wapper-lick', item)"
|
|
|
>
|
|
|
<image
|
|
|
class="waterfalls-list-image"
|
|
|
:class="{ single }"
|
|
|
mode="widthFix"
|
|
|
:style="imageStyle"
|
|
|
:src="item.image || ' '"
|
|
|
@load="imageLoadHandle(index)"
|
|
|
@error="imageLoadHandle(index)"
|
|
|
@click="$emit('image-click', item)"
|
|
|
/>
|
|
|
<view class="userInfo" @click="$emit('user-lick', item)" :style="{height: listType != 'mainAct' ? '90rpx' : '60rpx'}">
|
|
|
<view class="userDesc">
|
|
|
{{item.title}}
|
|
|
</view>
|
|
|
<view class="userIconLike" v-if="listType != 'mainAct'">
|
|
|
<view class="userIcon">
|
|
|
<image :src="item.user.avatar" mode=""></image>
|
|
|
{{item.user.nickname}}
|
|
|
</view>
|
|
|
<view class="likeNum">
|
|
|
<image src="../../static/image/dianzan2.png" mode=""></image>
|
|
|
{{item.like_num}}
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
<view class="statusTxt" v-if="listType == 'findPlay' && item.switch == '1'">
|
|
|
精选
|
|
|
</view>
|
|
|
<view class="statusTxt" v-if="listType == 'mainAct'">
|
|
|
{{item.state_text}}
|
|
|
</view>
|
|
|
<!-- "check_status": 审核状态:0=审核中,1=已通过,2=未通过 -->
|
|
|
<view class="statusTxt" v-if="listType == 'myStory' && item.check_status != '1'">
|
|
|
{{item.check_status == '0' ? '审核中' : '未通过'}}
|
|
|
</view>
|
|
|
</view>
|
|
|
<!-- #endif -->
|
|
|
</view>
|
|
|
</template>
|
|
|
<script>
|
|
|
export default {
|
|
|
props: {
|
|
|
showStatus:{type: Boolean,default:false},
|
|
|
list: { type: Array, required: true },
|
|
|
listType:{ type: String},
|
|
|
// offset 间距,单位为 px
|
|
|
offset: { type: Number, default: 10 },
|
|
|
// 列表渲染的 key 的键名,值必须唯一,默认为 id
|
|
|
idKey: { type: String, default: "id" },
|
|
|
// 图片 src 的键名
|
|
|
imageSrcKey: { type: String, default: "image_url" },
|
|
|
// 列数
|
|
|
cols: { type: Number, default: 2, validator: (num) => num >= 2 },
|
|
|
imageStyle: { type: Object },
|
|
|
|
|
|
// 是否是单独的渲染图片的样子,只控制图片圆角而已
|
|
|
single: { type: Boolean, default: false },
|
|
|
|
|
|
// #ifndef MP-WEIXIN
|
|
|
listStyle: { type: Object },
|
|
|
// #endif
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
topArr: [], // left, right 多个时依次表示第几列的数据
|
|
|
allPositionArr: [], // 保存所有的位置信息
|
|
|
allHeightArr: [], // 保存所有的 height 信息
|
|
|
height: 0, // 外层包裹高度
|
|
|
oldNum: 0,
|
|
|
num: 0,
|
|
|
};
|
|
|
},
|
|
|
created() {
|
|
|
this.refresh();
|
|
|
},
|
|
|
methods: {
|
|
|
imageLoadHandle(index) {
|
|
|
const id = "waterfalls-list-id-" + this.list[index][this.idKey],
|
|
|
query = uni.createSelectorQuery().in(this);
|
|
|
query
|
|
|
.select("#" + id)
|
|
|
.fields({ size: true }, (data) => {
|
|
|
this.num++;
|
|
|
this.$set(this.allHeightArr, index, data.height);
|
|
|
if(this.num === 1){
|
|
|
uni.showLoading({
|
|
|
title:'加载中...'
|
|
|
})
|
|
|
}
|
|
|
if (this.num === this.list.length) {
|
|
|
for (let i = this.oldNum; i < this.num; i++) {
|
|
|
const getTopArrMsg = () => {
|
|
|
let arrtmp = [...this.topArr].sort((a, b) => a - b);
|
|
|
return {
|
|
|
shorterIndex: this.topArr.indexOf(arrtmp[0]),
|
|
|
shorterValue: arrtmp[0],
|
|
|
longerIndex: this.topArr.indexOf(arrtmp[this.cols - 1]),
|
|
|
longerValue: arrtmp[this.cols - 1],
|
|
|
};
|
|
|
};
|
|
|
|
|
|
const { shorterIndex, shorterValue } = getTopArrMsg();
|
|
|
const position = {
|
|
|
top: shorterValue + "px",
|
|
|
left: (data.width + this.offset) * shorterIndex + "px",
|
|
|
};
|
|
|
this.$set(this.allPositionArr, i, position);
|
|
|
this.topArr[shorterIndex] =
|
|
|
shorterValue + this.allHeightArr[i] + this.offset;
|
|
|
this.height = getTopArrMsg().longerValue - this.offset;
|
|
|
}
|
|
|
this.oldNum = this.num;
|
|
|
uni.hideLoading()
|
|
|
// 完成渲染 emit `image-load` 事件
|
|
|
this.$emit("image-load");
|
|
|
}
|
|
|
})
|
|
|
.exec();
|
|
|
},
|
|
|
refresh() {
|
|
|
|
|
|
let arr = [];
|
|
|
for (let i = 0; i < this.cols; i++) {
|
|
|
arr.push(0);
|
|
|
}
|
|
|
this.topArr = arr;
|
|
|
this.num = 0;
|
|
|
this.oldNum = 0;
|
|
|
this.height = 0;
|
|
|
},
|
|
|
},
|
|
|
};
|
|
|
</script>
|
|
|
<style lang="scss" scoped>
|
|
|
// 这里可以自行配置
|
|
|
$border-radius: 10px;
|
|
|
|
|
|
.waterfalls-box {
|
|
|
position: relative;
|
|
|
width: 100%;
|
|
|
overflow: hidden;
|
|
|
.waterfalls-list {
|
|
|
position: relative;
|
|
|
width: calc((100% - var(--offset) * (var(--cols) - 1)) / var(--cols));
|
|
|
position: absolute;
|
|
|
background-color: #fff;
|
|
|
border-radius: $border-radius;
|
|
|
// 防止刚开始渲染时堆叠在第一幅图的地方
|
|
|
left: calc(-50% - var(--offset));
|
|
|
.waterfalls-list-image {
|
|
|
width: 100%;
|
|
|
will-change: transform;
|
|
|
border-radius: $border-radius;
|
|
|
display: block;
|
|
|
&.single {
|
|
|
border-radius: $border-radius;
|
|
|
}
|
|
|
}
|
|
|
.userInfo{
|
|
|
background: linear-gradient(135deg,rgba(0,0,0,0.00), rgba(0,0,0,0.60));
|
|
|
border-radius: 0 0 $border-radius $border-radius;
|
|
|
position:absolute;
|
|
|
bottom: 0;
|
|
|
width: 100%;
|
|
|
.userDesc{
|
|
|
font-size: 26rpx;
|
|
|
color: #fff;
|
|
|
padding: 0 24rpx;
|
|
|
overflow: hidden;
|
|
|
text-overflow: ellipsis;
|
|
|
display: -webkit-box;
|
|
|
-webkit-line-clamp:1;
|
|
|
-webkit-box-orient:vertical;
|
|
|
height: 45rpx;
|
|
|
line-height: 45rpx;
|
|
|
}
|
|
|
.userIconLike{
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
font-size: 20rpx;
|
|
|
color: rgba(255,255,255,0.80);
|
|
|
padding: 0 24rpx;
|
|
|
.userIcon{
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
image{width: 38rpx;height: 38rpx;margin-right: 10rpx;border-radius: 100%;}
|
|
|
}
|
|
|
.likeNum{
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
image{width: 28rpx;height: 28rpx;margin-right: 5rpx;}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
.statusTxt{
|
|
|
width: 100rpx;
|
|
|
height: 48rpx;
|
|
|
background: rgba(0,53,46,0.50);
|
|
|
text-align: center;
|
|
|
line-height: 48rpx;
|
|
|
font-size: 20rpx;
|
|
|
color:#fff;
|
|
|
position:absolute;
|
|
|
top: 0;
|
|
|
right: 0;
|
|
|
border-radius: 0 $border-radius 0 0;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</style> |