123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- <template>
- <div class="collections-list">
- <PageBanner :title="route.params.name as string" :img="bgImg" />
- <VanList
- v-model:loading="loading"
- :finished="noMore"
- finished-text="no more"
- :immediate-check="false"
- @load="onLoad"
- >
- <Waterfall
- background-color="#f7f6f3"
- :list="list"
- :breakpoints="{
- 500: { rowPerView: 2 },
- }"
- :gutter="20"
- >
- <template #item="{ item, url }">
- <div
- class="collections-list-card"
- @click="
- $router.push({
- name: 'CollectionsDetail',
- query: { id: item.id },
- })
- "
- >
- <VanImage :src="url" width="100%" :height="item.imgHeight + 'px'" />
- <p class="limit-line line-2">{{ item.name }}</p>
- </div>
- </template>
- </Waterfall>
- </VanList>
- </div>
- </template>
- <script lang="ts" setup>
- import { computed, ref, watch } from "vue";
- import { Waterfall } from "vue-waterfall-plugin-next";
- import { getBaseURL } from "@dage/service";
- import { getCollectionListApi, type CollectionListItem } from "@/api";
- import PageBanner from "@/components/PageBanner.vue";
- import { PaginationType, usePagination } from "@/utils/usePagination";
- import { useCollectionStore } from "@/stores/collection";
- import "vue-waterfall-plugin-next/dist/style.css";
- import { useRoute } from "vue-router";
- import { NAV_LIST } from "../constants";
- const baseUrl = getBaseURL();
- const collectionStore = useCollectionStore();
- const route = useRoute();
- // 当前页图片数据是否全部加载完成
- const rendering = ref(false);
- const list = ref<any[]>([]);
- const realType = computed(
- () => NAV_LIST.find((i) => i.type === (route.params.name as string))?.name
- );
- const bgImg = computed(
- () =>
- baseUrl +
- collectionStore.thumbList.find((i) => i.type === realType.value)?.thumb
- );
- const {
- pageNum,
- list: sourceList,
- noMore: _noMore,
- loading: fetchLoading,
- getList,
- } = usePagination<CollectionListItem>(
- (params) => {
- rendering.value = true;
- return getCollectionListApi({
- type: realType.value,
- ...params,
- });
- },
- PaginationType.DEFAULT,
- 20
- );
- const loading = computed(() => rendering.value || fetchLoading.value);
- const noMore = computed(() => !loading.value && _noMore.value);
- const onLoad = () => {
- // 检查用户是否滚动到页面底部
- if (!loading.value && !noMore.value && !rendering.value) {
- pageNum.value++;
- getList();
- }
- };
- watch(
- route,
- () => {
- pageNum.value = 1;
- list.value = [];
- getList();
- },
- {
- immediate: true,
- }
- );
- const ITEM_WIDTH = window.innerWidth / 2 - 60;
- watch(sourceList, async (v) => {
- if (!v.length) return;
- rendering.value = true;
- try {
- for (const i of v) {
- const url = baseUrl + i.thumb;
- const ratio = await getImgRatio(url);
- list.value.push({
- ...i,
- imgHeight: ITEM_WIDTH * ratio,
- src: url,
- });
- }
- } finally {
- setTimeout(() => {
- rendering.value = false;
- }, 500);
- }
- });
- const getImgRatio: (url: string) => Promise<number> = (url: string) => {
- return new Promise((res) => {
- const img = new Image();
- img.src = url;
- img.onload = () => {
- const ratio = Math.round((img.height / img.width) * 100) / 100;
- res(ratio);
- };
- img.onerror = () => {
- res(0);
- };
- });
- };
- </script>
- <style lang="scss" scoped>
- @import "./index.scss";
- </style>
|