feat: 优化收藏和历史列表组件,添加加载状态管理和动画效果

This commit is contained in:
alger
2025-05-24 19:23:38 +08:00
parent e5adb8aa72
commit 5070a085e9
3 changed files with 45 additions and 19 deletions
+18 -8
View File
@@ -80,6 +80,7 @@
:key="song.id" :key="song.id"
:item="song" :item="song"
:favorite="false" :favorite="false"
class="favorite-list-item"
:class="setAnimationClass('animate__bounceInLeft')" :class="setAnimationClass('animate__bounceInLeft')"
:style="getItemAnimationDelay(index)" :style="getItemAnimationDelay(index)"
:selectable="isSelecting" :selectable="isSelecting"
@@ -103,7 +104,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue'; import { computed, ref, watch, onMounted } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
@@ -339,20 +340,27 @@ const handleBatchDownload = async () => {
} }
}; };
const hasLoaded = ref(false);
onMounted(async () => { onMounted(async () => {
await playerStore.initializeFavoriteList(); if (!hasLoaded.value) {
await getFavoriteSongs(); await playerStore.initializeFavoriteList();
await getFavoriteSongs();
hasLoaded.value = true;
}
}); });
// 监听收藏列表变化 // 监听收藏列表变化,变化时重置并重新加载
watch( watch(
favoriteList, favoriteList,
() => { async () => {
hasLoaded.value = false;
currentPage.value = 1; currentPage.value = 1;
noMore.value = false; noMore.value = false;
getFavoriteSongs(); await getFavoriteSongs();
hasLoaded.value = true;
}, },
{ deep: true, immediate: true } { deep: true }
); );
const handlePlay = () => { const handlePlay = () => {
@@ -505,7 +513,9 @@ const handleBatchDownload = async () => {
.favorite-list { .favorite-list {
@apply space-y-2 pb-4 px-4; @apply space-y-2 pb-4 px-4;
&-item {
@apply bg-light-100 dark:bg-dark-100 hover:bg-light-200 dark:hover:bg-dark-200 transition-all;
}
&-more { &-more {
@apply mt-4; @apply mt-4;
+21 -9
View File
@@ -32,7 +32,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { getBilibiliProxyUrl, getBilibiliVideoDetail } from '@/api/bilibili'; import { getBilibiliProxyUrl, getBilibiliVideoDetail } from '@/api/bilibili';
@@ -42,11 +42,6 @@ import { useMusicHistory } from '@/hooks/MusicHistoryHook';
import { usePlayerStore } from '@/store/modules/player'; import { usePlayerStore } from '@/store/modules/player';
import type { SongResult } from '@/type/music'; import type { SongResult } from '@/type/music';
import { setAnimationClass, setAnimationDelay } from '@/utils'; import { setAnimationClass, setAnimationDelay } from '@/utils';
defineOptions({
name: 'History'
});
const { t } = useI18n(); const { t } = useI18n();
const { delMusic, musicList } = useMusicHistory(); const { delMusic, musicList } = useMusicHistory();
const scrollbarRef = ref(); const scrollbarRef = ref();
@@ -54,6 +49,7 @@ const loading = ref(false);
const noMore = ref(false); const noMore = ref(false);
const displayList = ref<SongResult[]>([]); const displayList = ref<SongResult[]>([]);
const playerStore = usePlayerStore(); const playerStore = usePlayerStore();
const hasLoaded = ref(false);
// 无限滚动相关配置 // 无限滚动相关配置
const pageSize = 100; const pageSize = 100;
@@ -178,10 +174,26 @@ const handlePlay = () => {
playerStore.setPlayList(displayList.value); playerStore.setPlayList(displayList.value);
}; };
onMounted(() => { onMounted(async () => {
getHistorySongs(); if (!hasLoaded.value) {
await getHistorySongs();
hasLoaded.value = true;
}
}); });
// 监听历史列表变化,变化时重置并重新加载
watch(
musicList,
async () => {
hasLoaded.value = false;
currentPage.value = 1;
noMore.value = false;
await getHistorySongs();
hasLoaded.value = true;
},
{ deep: true }
);
// 重写删除方法,需要同时更新 displayList // 重写删除方法,需要同时更新 displayList
const handleDelMusic = async (item: SongResult) => { const handleDelMusic = async (item: SongResult) => {
delMusic(item); delMusic(item);
@@ -205,7 +217,7 @@ const handleDelMusic = async (item: SongResult) => {
.history-item { .history-item {
@apply flex items-center justify-between; @apply flex items-center justify-between;
&-content { &-content {
@apply flex-1; @apply flex-1 bg-light-100 dark:bg-dark-100 hover:bg-light-200 dark:hover:bg-dark-200 transition-all;
} }
&-count { &-count {
@apply px-4 text-lg text-center; @apply px-4 text-lg text-center;
@@ -1,13 +1,17 @@
<template> <template>
<div class="flex gap-4 h-full pb-4"> <div class="flex gap-4 h-full pb-4">
<favorite class="flex-item" /> <favorite class="flex-item" />
<history class="flex-item" /> <history-list class="flex-item" />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
defineOptions({
name: 'History'
});
import Favorite from '@/views/favorite/index.vue'; import Favorite from '@/views/favorite/index.vue';
import History from '@/views/history/index.vue'; import HistoryList from '@/views/history/index.vue';
</script> </script>
<style scoped> <style scoped>