youdas/components/youdas-container/news-list-item.vue
2025-06-21 23:03:06 +08:00

206 lines
5.0 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 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>