206 lines
5.0 KiB
Vue
206 lines
5.0 KiB
Vue
<template>
|
||
<view class="content">
|
||
<z-paging v-if="firstLoaded || isCurrentPage" ref="paging" show-refresher-update-time
|
||
loading-more-no-more-text="我也是有底线的!" v-model="dataList" @query="queryList" :fixed="false">
|
||
<template v-for="(item, index) in dataList">
|
||
<view v-if="item.cover_image !== ''" class="view-data" :key="index" @click="toDetails(item.id)">
|
||
<view class="title">
|
||
{{ item.title }}
|
||
</view>
|
||
|
||
<view class="time">
|
||
{{ item.publish_time }}
|
||
</view>
|
||
|
||
<view class="img">
|
||
<image :src="item.cover_image" mode="aspectFill" style="width: 225.19rpx; height: 158.4rpx;" />
|
||
</view>
|
||
<view class="item-line"></view>
|
||
</view>
|
||
<view v-else class="view-data" :key="`no-img-${index}`" @click="toDetails(item.id)">
|
||
<view class="title-no-img">
|
||
{{ item.title }}
|
||
</view>
|
||
|
||
<view class="time">
|
||
{{ item.publish_time }}
|
||
</view>
|
||
<view class="item-line"></view>
|
||
</view>
|
||
</template>
|
||
|
||
<template #empty>
|
||
<no-data />
|
||
</template>
|
||
<template #loading>
|
||
<loading-data />
|
||
</template>
|
||
</z-paging>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
const paging = ref(null);
|
||
const dataList = ref([]);
|
||
// 当前组件是否已经加载过了
|
||
const firstLoaded = ref(false);
|
||
// 是否滚动到当前页
|
||
const isCurrentPage = ref(false);
|
||
|
||
// 跳转到详情页
|
||
const toDetails = (id) => {
|
||
if (!id) return;
|
||
emit('clickItem', id);
|
||
}
|
||
|
||
const props = defineProps({
|
||
tabIndex: {
|
||
type: Number,
|
||
default: 0
|
||
},
|
||
currentIndex: {
|
||
type: Number,
|
||
default: 0
|
||
},
|
||
responseCallback: {
|
||
type: Function,
|
||
default: null
|
||
}
|
||
});
|
||
|
||
// 定义可触发的事件
|
||
const emit = defineEmits(['clickItem']);
|
||
|
||
watch(() => props.currentIndex, (newVal) => {
|
||
if (newVal === props.tabIndex) {
|
||
// 懒加载,当滑动到当前的item时,才去加载
|
||
if (!firstLoaded.value) {
|
||
// 这里需要延迟渲染z-paging的原因是为了避免在一些平台上立即渲染可能引发的底层报错问题
|
||
setTimeout(() => {
|
||
isCurrentPage.value = true;
|
||
}, 50);
|
||
}
|
||
}
|
||
}, {
|
||
immediate: true
|
||
});
|
||
|
||
const queryList = (pageNo, pageSize) => {
|
||
if (!props.responseCallback) { paging.value.complete(false); return; };
|
||
|
||
const params = {
|
||
pageNo: pageNo,
|
||
pageSize: pageSize,
|
||
type: props.tabIndex
|
||
};
|
||
|
||
try {
|
||
props.responseCallback(params).then(res => {
|
||
if (paging.value) {
|
||
paging.value.complete(res.list || []);
|
||
firstLoaded.value = true;
|
||
}
|
||
}).catch(err => {
|
||
if (paging.value) {
|
||
paging.value.complete(false);
|
||
}
|
||
console.error('获取新闻列表失败', err);
|
||
});
|
||
} catch (e) {
|
||
console.error('调用responseCallback异常', e);
|
||
if (paging.value) {
|
||
paging.value.complete(false);
|
||
}
|
||
}
|
||
};
|
||
|
||
// 添加刷新数据方法
|
||
const refresh = () => {
|
||
if (paging.value) {
|
||
paging.value.reload();
|
||
}
|
||
};
|
||
|
||
// 重置数据
|
||
const reset = () => {
|
||
if (paging.value) {
|
||
paging.value.clear();
|
||
}
|
||
dataList.value = [];
|
||
firstLoaded.value = false;
|
||
};
|
||
|
||
// 暴露方法供父组件调用
|
||
defineExpose({
|
||
refresh,
|
||
reset
|
||
});
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.content {
|
||
height: 100%;
|
||
}
|
||
|
||
.view-data {
|
||
width: 100%;
|
||
height: 225.19rpx;
|
||
background-color: white;
|
||
margin-bottom: 15rpx;
|
||
border-radius: 19.08rpx;
|
||
position: relative;
|
||
|
||
|
||
.title {
|
||
width: 366.41rpx;
|
||
height: 83.97rpx;
|
||
position: absolute;
|
||
top: 32rpx;
|
||
left: 20rpx;
|
||
-webkit-line-clamp: 2;
|
||
-webkit-box-orient: vertical;
|
||
display: -webkit-box;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.time {
|
||
position: absolute;
|
||
left: 20rpx;
|
||
font-size: 22.9rpx;
|
||
color: #878787;
|
||
bottom: 24rpx;
|
||
}
|
||
|
||
.img {
|
||
position: absolute;
|
||
right: 20rpx;
|
||
top: 34rpx;
|
||
width: 225.19rpx;
|
||
height: 158.4rpx;
|
||
background-color: #D8D8D8;
|
||
}
|
||
|
||
.title-no-img {
|
||
width: calc(100% - 40rpx);
|
||
height: 83.97rpx;
|
||
position: absolute;
|
||
top: 20rpx;
|
||
left: 20rpx;
|
||
-webkit-line-clamp: 2;
|
||
-webkit-box-orient: vertical;
|
||
display: -webkit-box;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.item-line {
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 0;
|
||
height: 1px;
|
||
width: 100%;
|
||
background-color: #eeeeee;
|
||
}
|
||
}
|
||
</style> |