feat: 添加加载图标和分页逻辑,优化数据获取体验

This commit is contained in:
傅光孟 2026-02-12 22:33:31 +08:00
parent a7a3a08ee3
commit d4cbc2c562
3 changed files with 99 additions and 14 deletions

View File

@ -75,6 +75,15 @@
</view>
</view>
</view>
<u-loading-icon
v-if="!isBottom && loading"
mode="circle"
text="加载中..."
textSize="26rpx"
textColor="#999999"
color="rgba(23, 119, 255, 1)"
size="28rpx"
></u-loading-icon>
</view>
<!-- 登录弹窗 start -->
@ -91,8 +100,9 @@
<script setup lang="ts">
import { getForeignList } from "@/api";
import { useUserStore } from "@/stores/user";
import { computed, onMounted, ref } from "vue";
import { computed, onMounted, reactive, ref } from "vue";
import LoginDialog from "@/components/loginPopup/index.vue";
import { onReachBottom } from "@dcloudio/uni-app";
//
const handleBack = () => {
@ -143,23 +153,40 @@ function goDetail(item: any) {
}
const data = ref([]);
const loading = ref(false);
const keyword = ref("");
const isBottom = ref(false);
const pages = reactive({
page: 1,
size: 20,
total: 0,
});
const getList = async () => {
const result = await getForeignList({
keyword: keyword.value,
page: pages.page,
size: pages.size,
});
if (result.code === 200) {
const { list, total } = result.data;
data.value = list;
data.value = [...data.value, ...list];
pages.total = Math.ceil(total / pages.size);
isBottom.value = pages.page >= pages.total;
} else {
data.value = [];
}
};
const keyword = ref("");
const handleSearch = () => {
getList();
};
onReachBottom(() => {
if (isBottom.value) return;
pages.page++;
getList();
});
onMounted(async () => {
if (!userStore.isLogin) {
handleShowLogin();

View File

@ -16,8 +16,7 @@
<!-- 标题 end -->
<view class="page-main">
<u-loading-icon v-if="loading"></u-loading-icon>
<view class="news-list" v-else-if="data?.length > 0">
<view class="news-list" v-if="data?.length > 0">
<template v-for="(item, index) in data" :key="index">
<view
:class="['news-item', { mask: !userStore.isLogin }]"
@ -42,6 +41,15 @@
</template>
</view>
<u-empty v-else />
<u-loading-icon
v-if="!isBottom && loading"
mode="circle"
text="加载中..."
textSize="26rpx"
textColor="#999999"
color="rgba(23, 119, 255, 1)"
size="28rpx"
></u-loading-icon>
</view>
<!-- 登录弹窗 start -->
<LoginDialog
@ -57,8 +65,9 @@
<script setup lang="ts">
import { getMacroList } from "@/api";
import { useUserStore } from "@/stores/user";
import { computed, onMounted, ref } from "vue";
import { computed, onMounted, reactive, ref } from "vue";
import LoginDialog from "@/components/loginPopup/index.vue";
import { onReachBottom } from "@dcloudio/uni-app";
//
const handleBack = () => {
uni.navigateBack({
@ -109,18 +118,37 @@ function goDetail(item: any) {
const data = ref([]);
const loading = ref(false);
const keyword = ref("");
const isBottom = ref(false);
const pages = reactive({
page: 1,
size: 20,
total: 0,
});
const getList = async () => {
loading.value = true;
const result = await getMacroList({});
const result = await getMacroList({
keyword: keyword.value,
page: pages.page,
size: pages.size,
});
loading.value = false;
if (result.code === 200) {
const { list, total } = result.data;
data.value = list;
data.value = [...data.value, ...list];
pages.total = Math.ceil(total / pages.size);
isBottom.value = pages.page >= pages.total;
} else {
data.value = [];
}
};
onReachBottom(() => {
if (isBottom.value) return;
pages.page++;
getList();
});
onMounted(async () => {
if (!userStore.isLogin) {
handleShowLogin();

View File

@ -35,6 +35,7 @@
</view>
<!-- 时间轴 start -->
<view class="page-timeline">
<view
:class="['timeline', { mask: !userStore.isLogin }]"
@ -110,6 +111,15 @@
</view>
</view>
</view>
<u-loading-icon
v-if="!isBottom && loading"
mode="circle"
text="加载中..."
textSize="26rpx"
textColor="#999999"
color="rgba(23, 119, 255, 1)"
size="28rpx"
></u-loading-icon>
</view>
<!-- 时间轴 end -->
</view>
@ -128,8 +138,9 @@
<script setup lang="ts">
import { getRecommendList } from "@/api";
import { useUserStore } from "@/stores/user";
import { computed, onMounted, ref } from "vue";
import { computed, onMounted, reactive, ref } from "vue";
import LoginDialog from "@/components/loginPopup/index.vue";
import { onReachBottom } from "@dcloudio/uni-app";
//
const handleBack = () => {
uni.navigateBack({
@ -192,29 +203,46 @@ function goDetail(item: any) {
}
const data = ref([]);
const loading = ref(false);
const keyword = ref("");
const isBottom = ref(false);
const pages = reactive({
page: 1,
size: 20,
total: 0,
});
const getList = async () => {
loading.value = true;
const result = await getRecommendList({
keyword: keyword.value,
page: pages.page,
size: pages.size,
});
loading.value = false;
if (result.code === 200) {
const { list, total } = result.data;
data.value = list;
data.value = [...data.value, ...list];
list.forEach((o) => {
o.list.forEach((n) => {
selectKeys.value.push(n.id)
selectKeys.value.push(n.id);
});
});
pages.total = Math.ceil(total / pages.size);
isBottom.value = pages.page >= pages.total;
} else {
data.value = [];
}
};
const keyword = ref("");
const handleSearch = () => {
getList();
};
onReachBottom(() => {
if (isBottom.value) return;
pages.page++;
getList();
});
onMounted(async () => {
if (!userStore.isLogin) {
handleShowLogin();
@ -327,6 +355,7 @@ onMounted(async () => {
.page-timeline {
position: relative;
z-index: 3;
padding-bottom: 20rpx;
.mask {
filter: blur(5px);
@ -364,6 +393,7 @@ onMounted(async () => {
}
.content {
flex: 1;
padding: 0 0 30rpx 15rpx;
}