feat: 重构心动模式与私人FM播放逻辑

- 心动模式从播放模式循环中独立,移至 SearchBar 作为独立按钮
- 新增私人FM自动续播:播放结束后自动获取下一首
- 播放列表设置时自动清除FM模式标志
- 顺序播放模式播放到最后一首后正确停止
- 新增获取关注歌手新歌 API
- 补充心动模式相关 i18n 翻译
This commit is contained in:
alger
2026-03-22 16:49:00 +08:00
parent 7f0b3c6469
commit 2b8378bbae
12 changed files with 127 additions and 38 deletions
@@ -105,6 +105,24 @@
</n-badge>
</button>
<!-- 心动模式按钮 -->
<n-tooltip v-if="showIntelligenceBtn" trigger="hover">
<template #trigger>
<button
class="action-btn"
:class="{ 'intelligence-active': isIntelligenceMode }"
@click="toggleIntelligenceMode"
>
<i class="ri-heart-pulse-line" />
</button>
</template>
{{
isIntelligenceMode
? t('comp.searchBar.exitIntelligence')
: t('comp.searchBar.intelligenceMode')
}}
</n-tooltip>
<!-- 用户 -->
<n-popover trigger="hover" placement="bottom-end" :show-arrow="false" raw>
<template #trigger>
@@ -205,6 +223,7 @@ import Coffee from '@/components/Coffee.vue';
import { SEARCH_TYPES, USER_SET_OPTIONS } from '@/const/bar-const';
import { useDownloadStatus } from '@/hooks/useDownloadStatus';
import { useZoom } from '@/hooks/useZoom';
import { useIntelligenceModeStore } from '@/store/modules/intelligenceMode';
import { useNavTitleStore } from '@/store/modules/navTitle';
import { useSearchStore } from '@/store/modules/search';
import { useSettingsStore } from '@/store/modules/settings';
@@ -223,6 +242,7 @@ const userStore = useUserStore();
const userSetOptions = ref(USER_SET_OPTIONS);
const { t, locale } = useI18n();
const intelligenceModeStore = useIntelligenceModeStore();
const { downloadingCount, navigateToDownloads } = useDownloadStatus();
const showDownloadButton = computed(
() =>
@@ -230,6 +250,17 @@ const showDownloadButton = computed(
);
const { zoomFactor, initZoomFactor, increaseZoom, decreaseZoom, resetZoom, isZoom100 } = useZoom();
// ── 心动模式 ─────────────────────────────────────────
const isIntelligenceMode = computed(() => intelligenceModeStore.isIntelligenceMode);
const showIntelligenceBtn = computed(() => userStore.user && userStore.loginType === 'cookie');
const toggleIntelligenceMode = async () => {
if (isIntelligenceMode.value) {
intelligenceModeStore.clearIntelligenceMode();
} else {
await intelligenceModeStore.playIntelligenceMode();
}
};
// ── Back button ───────────────────────────────────────
const showBackButton = computed(() => {
const meta = router.currentRoute.value.meta;
@@ -681,6 +712,16 @@ onMounted(() => {
background: rgba(34, 197, 94, 0.08);
color: #22c55e;
}
.action-btn.intelligence-active {
color: #ec4899;
border-color: #fbcfe8;
background: #fdf2f8;
}
.dark .action-btn.intelligence-active {
color: #ec4899;
border-color: #831843;
background: rgba(236, 72, 153, 0.1);
}
/* ── User button ─────────────────────────────────────── */
.user-btn {