文件
OmniCard/mpuniapp/pages/template/banner-waterfall-nested-scroll/long-waterflow-page.uvue

218 行
5.3 KiB
Plaintext

<template>
<waterflow :id="id" class="grid" :bounces="false" :scroll-y="true" :custom-nested-scroll="true"
main-axis-gap="8px" cross-axis-gap="8px" cross-axis-count=2
@scrolltolower="loadData(null)" associative-container="nested-scroll-view">
<flow-item class="flow-item" v-for="(item, _) in datagrid" :key="item.plugin_id" type=1>
<view class="flow-item-icon">
<image class="flow-item-icon-image" :src="item.plugin_img_link" mode="aspectFit"></image>
</view>
<view class="flow-item-fill">
<view class="flex-row">
<text class="title">{{item.plugin_name}}</text>
</view>
<view>
<text class="description-text">{{item.plugin_intro}}</text>
</view>
<uni-rate :value="(item.score as number) / 10" :full="true" :readonly="true"></uni-rate>
<view class="tag-grid">
<text class="tag-item" v-for="(item2, index2) in (item.tags as Array<string>).slice(0,1)" :key="index2">{{item2}}</text>
</view>
<view class="flex-row update-date">
<text class="author">{{item.author_name}}</text>
</view>
<view class="flex-row update-date">
<text class="update-date-text">更新日期</text>
<text class="update-date-value">{{item.update_date}}</text>
</view>
</view>
</flow-item type="20">
<flow-item slot="load-more" class="loading" type=6>
<!-- <uni-loading :loading="loading" color="#999" :text="loadingText"></uni-loading> -->
<loading v-if="loadingRef" style="color: #999"></loading>
<text v-if="isEnded" style="color: #999">到底了</text>
</flow-item>
</waterflow>
</template>
<script setup lang="uts">
/**
* @description: 作为瀑布流内容页,支持按分类加载卡片数据并在滚动到底部后继续追加内容。
* @logic: 页面根据父级传入的分类参数请求瀑布流接口,首次显示时按需预加载,触底后继续请求下一页并更新瀑布流数据源。
* @optimization: 通过 `preload` 控制首次请求时机,避免所有标签页同时加载;瀑布流列表采用分页追加方式,降低首屏数据量和布局压力。
*/
const SERVER_URL = "https://unidemo.dcloud.net.cn/plugin/uniappx-plugin-list"
const PAGE_SIZE = 10; // 最大值 10
type flowItem = {
plugin_id : number,
plugin_img_link : string,
plugin_name : string,
plugin_intro : string,
score : number,
tags : Array<string>,
update_date : string,
author_name : string,
}
type ResponseDataType = {
code : number,
data : flowItem[]
}
const props = defineProps({
type: { type: String, default: '' },
preload: { type: Boolean, default: false },
id: { type: String, default: '' }
})
const loadingRef = ref(false);
const datagrid = ref([] as flowItem[]);
const isEnded = ref(false);
const loadingError = ref('');
const currentPage = ref(1);
const loadingText = computed(() : string => {
if (loadingRef.value) {
return "加载中..."
} else if (isEnded.value) {
return "没有更多了"
} else if (loadingError.value.length > 0) {
return loadingError.value
} else {
return ""
}
});
function loadData(loadComplete : (() => void) | null) {
if (loadingRef.value || isEnded.value) {
return
}
loadingRef.value = true
uni.request<ResponseDataType>({
url: SERVER_URL,
data: {
type: props.type,
page: currentPage.value,
page_size: PAGE_SIZE
},
success: (res) => {
const responseData = res.data
if (responseData == null) {
return
}
datagrid.value.push(...responseData.data)
if (responseData.data.length == 0) {
isEnded.value = true
} else {
currentPage.value++
}
},
fail: (err) => {
loadingError.value = err.errMsg
},
complete: () => {
loadingRef.value = false
if (loadComplete != null) {
loadComplete()
}
}
})
}
function refreshData(loadComplete : (() => void) | null) {
datagrid.value.length = 0
currentPage.value = 1
loadData(loadComplete)
}
onMounted(() => {
if (props.preload) {
loadData(null)
}
});
defineExpose({
refreshData,
loadData
});
</script>
<style>
.grid {
flex: 1;
background-color: #f7f7f7;
}
.flow-item {
flex-direction: column;
border-radius: 5px;
background-color: #ffffff;
}
.flow-item-icon {
position: relative;
}
.flow-item-icon-image {
width: 100%;
}
.flow-item-fill {
flex: 1;
padding: 5px;
}
.description-text {
font-size: 13px;
color: #666;
line-height: 19px;
}
.tag-grid {
flex-direction: row;
margin-top: 5px;
}
.tag-item {
font-size: 12px;
background-color: #EFF9F0;
color: #639069;
border-radius: 20px;
margin-right: 5px;
padding: 2px 5px;
}
.update-date {
margin-top: 10px;
}
.update-date-text {
font-size: 12px;
color: #888888;
}
.update-date-value {
font-size: 12px;
color: #777777;
margin-left: 5px;
}
.author {
font-size: 12px;
color: #008000;
}
.loading {
padding: 30px;
align-items: center;
height: 80px;
}
.flex-row {
flex-direction: row;
}
</style>