mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-03 14:20:50 +08:00
feat: 歌曲右键 添加不喜欢功能以过滤每日推荐歌曲
This commit is contained in:
@@ -6,7 +6,9 @@ export default {
|
||||
addToPlaylist: 'Add to Playlist',
|
||||
favorite: 'Like',
|
||||
unfavorite: 'Unlike',
|
||||
removeFromPlaylist: 'Remove from Playlist'
|
||||
removeFromPlaylist: 'Remove from Playlist',
|
||||
dislike: 'Dislike',
|
||||
undislike: 'Undislike',
|
||||
},
|
||||
message: {
|
||||
downloading: 'Downloading, please wait...',
|
||||
@@ -14,5 +16,13 @@ export default {
|
||||
downloadQueued: 'Added to download queue',
|
||||
addedToNextPlay: 'Added to play next',
|
||||
getUrlFailed: 'Failed to get music download URL, please check if logged in'
|
||||
},
|
||||
dialog: {
|
||||
dislike:{
|
||||
title: 'Dislike',
|
||||
content: 'Are you sure you want to dislike this song?',
|
||||
positiveText: 'Dislike',
|
||||
negativeText: 'Cancel'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6,7 +6,9 @@ export default {
|
||||
addToPlaylist: '添加到歌单',
|
||||
favorite: '喜欢',
|
||||
unfavorite: '取消喜欢',
|
||||
removeFromPlaylist: '从歌单中删除'
|
||||
removeFromPlaylist: '从歌单中删除',
|
||||
dislike: '不喜欢',
|
||||
undislike: '取消不喜欢',
|
||||
},
|
||||
message: {
|
||||
downloading: '正在下载中,请稍候...',
|
||||
@@ -14,5 +16,13 @@ export default {
|
||||
downloadQueued: '已加入下载队列',
|
||||
addedToNextPlay: '已添加到下一首播放',
|
||||
getUrlFailed: '获取音乐下载地址失败,请检查是否登录'
|
||||
},
|
||||
dialog: {
|
||||
dislike: {
|
||||
title: '提示!',
|
||||
content: '确认不喜欢这首歌吗?再次进入将从每日推荐中排除。',
|
||||
positiveText: '不喜欢',
|
||||
negativeText: '取消'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { cloneDeep } from 'lodash';
|
||||
import type { MenuOption } from 'naive-ui';
|
||||
import { NEllipsis, NImage, useMessage } from 'naive-ui';
|
||||
import { NEllipsis, NImage, useMessage, useDialog } from 'naive-ui';
|
||||
import { computed, h, inject, ref, useTemplateRef } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
@@ -307,7 +307,13 @@ const dropdownOptions = computed<MenuOption[]>(() => {
|
||||
h('i', {
|
||||
class: `iconfont ${isFavorite.value ? 'ri-heart-fill text-red-500' : 'ri-heart-line'}`
|
||||
})
|
||||
}
|
||||
},
|
||||
// 不喜欢
|
||||
{
|
||||
label: isDislike.value ? t('songItem.menu.undislike') : t('songItem.menu.dislike'),
|
||||
key: 'dislike',
|
||||
icon: () => h('i', { class: `iconfont ${isDislike.value ? 'ri-dislike-fill text-green-500': 'ri-dislike-line'}` })
|
||||
},
|
||||
];
|
||||
|
||||
if (props.canRemove) {
|
||||
@@ -343,18 +349,30 @@ const handleMenuClick = (e: MouseEvent) => {
|
||||
|
||||
const handleSelect = (key: string | number) => {
|
||||
showDropdown.value = false;
|
||||
if (key === 'download') {
|
||||
downloadMusic();
|
||||
} else if (key === 'playNext') {
|
||||
handlePlayNext();
|
||||
} else if (key === 'addToPlaylist') {
|
||||
openPlaylistDrawer?.(props.item.id);
|
||||
} else if (key === 'favorite') {
|
||||
toggleFavorite(new Event('click'));
|
||||
} else if (key === 'play') {
|
||||
playMusicEvent(props.item);
|
||||
} else if (key === 'remove') {
|
||||
emits('remove-song', props.item.id);
|
||||
switch (key) {
|
||||
case 'download':
|
||||
downloadMusic();
|
||||
break;
|
||||
case 'playNext':
|
||||
handlePlayNext();
|
||||
break;
|
||||
case 'addToPlaylist':
|
||||
openPlaylistDrawer?.(props.item.id);
|
||||
break;
|
||||
case 'favorite':
|
||||
toggleFavorite(new Event('click'));
|
||||
break;
|
||||
case 'play':
|
||||
playMusicEvent(props.item);
|
||||
break;
|
||||
case 'remove':
|
||||
emits('remove-song', props.item.id);
|
||||
break;
|
||||
case 'dislike':
|
||||
toggleDislike(new Event('click'));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -463,6 +481,12 @@ const isFavorite = computed(() => {
|
||||
return playerStore.favoriteList.includes(numericId);
|
||||
});
|
||||
|
||||
const isDislike = computed(() => {
|
||||
// 将id转换为number,兼容B站视频ID
|
||||
const numericId = typeof props.item.id ==='string'? parseInt(props.item.id, 10) : props.item.id;
|
||||
return playerStore.dislikeList.includes(numericId);
|
||||
})
|
||||
|
||||
// 切换收藏状态
|
||||
const toggleFavorite = async (e: Event) => {
|
||||
e.stopPropagation();
|
||||
@@ -475,6 +499,24 @@ const toggleFavorite = async (e: Event) => {
|
||||
playerStore.addToFavorite(numericId);
|
||||
}
|
||||
};
|
||||
const dialog = useDialog();
|
||||
const toggleDislike = async (e: Event) => {
|
||||
e.stopPropagation();
|
||||
if (isDislike.value) {
|
||||
playerStore.removeFromDislikeList(props.item.id);
|
||||
return;
|
||||
}
|
||||
dialog.warning({
|
||||
title: t('songItem.dialog.dislike.title'),
|
||||
content: t('songItem.dialog.dislike.content'),
|
||||
positiveText: t('songItem.dialog.dislike.positiveText'),
|
||||
negativeText: t('songItem.dialog.dislike.negativeText'),
|
||||
onPositiveClick: () => {
|
||||
playerStore.addToDislikeList(props.item.id);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// 切换选择状态
|
||||
const toggleSelect = () => {
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
<div class="mt-2">
|
||||
<p
|
||||
v-for="item in dayRecommendData?.dailySongs.slice(0, 5)"
|
||||
v-for="item in getDisplayDaySongs.slice(0, 5)"
|
||||
:key="item.id"
|
||||
class="text-el"
|
||||
>
|
||||
@@ -250,13 +250,16 @@ const loadArtistData = async () => {
|
||||
// 加载不需要登录的数据
|
||||
const loadNonUserData = async () => {
|
||||
try {
|
||||
|
||||
// 获取每日推荐
|
||||
try {
|
||||
// 获取每日推荐
|
||||
try {
|
||||
const {
|
||||
data: { data: dayRecommend }
|
||||
} = await getDayRecommend();
|
||||
dayRecommendData.value = dayRecommend as unknown as IDayRecommend;
|
||||
const dayRecommendSource = dayRecommend as unknown as IDayRecommend;
|
||||
dayRecommendData.value = {
|
||||
...dayRecommendSource,
|
||||
dailySongs: dayRecommendSource.dailySongs.filter((song: any) =>!playerStore.dislikeList.includes(song.id))
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('获取每日推荐失败:', error);
|
||||
}
|
||||
@@ -288,6 +291,12 @@ const loadUserData = async () => {
|
||||
const handleArtistClick = (id: number) => {
|
||||
navigateToArtist(id);
|
||||
};
|
||||
const getDisplayDaySongs = computed(() => {
|
||||
if(!dayRecommendData.value){
|
||||
return [];
|
||||
}
|
||||
return dayRecommendData.value.dailySongs.filter((song) => !playerStore.dislikeList.includes(song.id));
|
||||
})
|
||||
|
||||
const showDayRecommend = () => {
|
||||
if (!dayRecommendData.value?.dailySongs) return;
|
||||
@@ -295,7 +304,7 @@ const showDayRecommend = () => {
|
||||
navigateToMusicList(router, {
|
||||
type: 'dailyRecommend',
|
||||
name: t('comp.recommendSinger.songlist'),
|
||||
songList: dayRecommendData.value.dailySongs,
|
||||
songList: getDisplayDaySongs.value,
|
||||
canRemove: false
|
||||
});
|
||||
};
|
||||
|
||||
@@ -388,6 +388,7 @@ export const usePlayerStore = defineStore('player', () => {
|
||||
const playMode = ref(getLocalStorageItem('playMode', 0));
|
||||
const musicFull = ref(false);
|
||||
const favoriteList = ref<Array<number | string>>(getLocalStorageItem('favoriteList', []));
|
||||
const dislikeList = ref<Array<number | string>>(getLocalStorageItem('dislikeList', []));
|
||||
const savedPlayProgress = ref<number | undefined>();
|
||||
const showSleepTimer = ref(false); // 定时弹窗
|
||||
// 添加播放列表抽屉状态
|
||||
@@ -1031,6 +1032,16 @@ export const usePlayerStore = defineStore('player', () => {
|
||||
localStorage.setItem('favoriteList', JSON.stringify(favoriteList.value));
|
||||
};
|
||||
|
||||
const addToDislikeList = (id: number | string) => {
|
||||
dislikeList.value.push(id);
|
||||
localStorage.setItem('dislikeList', JSON.stringify(dislikeList.value));
|
||||
}
|
||||
|
||||
const removeFromDislikeList = (id: number | string) => {
|
||||
dislikeList.value = dislikeList.value.filter(existingId => existingId!== id);
|
||||
localStorage.setItem('dislikeList', JSON.stringify(dislikeList.value));
|
||||
}
|
||||
|
||||
const removeFromPlayList = (id: number | string) => {
|
||||
const index = playList.value.findIndex((item) => item.id === id);
|
||||
if (index === -1) return;
|
||||
@@ -1324,6 +1335,7 @@ export const usePlayerStore = defineStore('player', () => {
|
||||
musicFull,
|
||||
savedPlayProgress,
|
||||
favoriteList,
|
||||
dislikeList,
|
||||
playListDrawerVisible,
|
||||
|
||||
// 定时关闭相关
|
||||
@@ -1358,6 +1370,8 @@ export const usePlayerStore = defineStore('player', () => {
|
||||
addToFavorite,
|
||||
removeFromFavorite,
|
||||
removeFromPlayList,
|
||||
addToDislikeList,
|
||||
removeFromDislikeList,
|
||||
playAudio,
|
||||
reparseCurrentSong,
|
||||
setPlayListDrawerVisible,
|
||||
|
||||
@@ -238,6 +238,11 @@ onMounted(() => {
|
||||
});
|
||||
|
||||
// 从 pinia 或路由参数获取数据
|
||||
|
||||
// 从路由参数获取
|
||||
const routeId = route.params.id as string;
|
||||
const routeType = route.query.type as string;
|
||||
|
||||
const initData = () => {
|
||||
// 优先从 pinia 获取数据
|
||||
if (musicStore.currentMusicList) {
|
||||
@@ -251,9 +256,7 @@ const initData = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
// 从路由参数获取
|
||||
const routeId = route.params.id as string;
|
||||
const routeType = route.query.type as string;
|
||||
|
||||
|
||||
if (routeId) {
|
||||
// 这里根据 type 和 id 加载数据
|
||||
@@ -323,14 +326,22 @@ const getCoverImgUrl = computed(() => {
|
||||
return '';
|
||||
});
|
||||
|
||||
const getDisplaySongs = computed(() => {
|
||||
if(routeType === 'dailyRecommend') {
|
||||
return displayedSongs.value.filter((song) => !playerStore.dislikeList.includes(song.id));
|
||||
}else {
|
||||
return displayedSongs.value;
|
||||
}
|
||||
})
|
||||
|
||||
// 过滤歌曲列表
|
||||
const filteredSongs = computed(() => {
|
||||
if (!searchKeyword.value) {
|
||||
return displayedSongs.value;
|
||||
return getDisplaySongs.value;
|
||||
}
|
||||
|
||||
const keyword = searchKeyword.value.toLowerCase().trim();
|
||||
return displayedSongs.value.filter((song) => {
|
||||
return getDisplaySongs.value.filter((song) => {
|
||||
const songName = song.name?.toLowerCase() || '';
|
||||
const albumName = song.al?.name?.toLowerCase() || '';
|
||||
const artists = song.ar || song.artists || [];
|
||||
|
||||
Reference in New Issue
Block a user