feat(qq): add radar FM stream

This commit is contained in:
lTinchl committed 2026-06-06 21:09:57 +08:00
1 parent a861b41809
commit e0d17cf404
6 files changed
+217 -84

No files matched your search

+11
View File
@@ -397,6 +397,17 @@ export const usePlayerStore = defineStore('player', {
if (bot) bot.playMode = mode;
},
async startFm(platform: Source = 'netease') {
if (!this.activeBotId) return;
const res = await axios.post(`/api/player/${this.activeBotId}/fm`, { platform });
if (res.data?.message) {
this.notify(res.data.message, res.data.ok === false ? 'error' : 'info');
}
this._setTiming(this.activeBotId, { serverElapsed: 0 });
this._syncAfterAction();
this.fetchQueue();
},
async fetchHomeData() {
// Always check auth status first — if it changed since the cached
// fetch (e.g., user logged in/out as a different account), the
+19 -16
View File
@@ -21,7 +21,7 @@
<!-- 私人FM -->
<section class="section">
<h2 class="section-title">私人FM</h2>
<div class="fm-card hover-scale" @click="playFm">
<div class="fm-card hover-scale" @click="playFm('netease')">
<div class="fm-icon-wrapper">
<Icon icon="mdi:radio" class="fm-icon" />
</div>
@@ -31,6 +31,16 @@
</div>
<Icon icon="mdi:play-circle" class="fm-play-icon" />
</div>
<div v-if="store.authStatus.qq" class="fm-card hover-scale" @click="playFm('qq')">
<div class="fm-icon-wrapper qq">
<Icon icon="mdi:radar" class="fm-icon" />
</div>
<div class="fm-info">
<div class="fm-title">QQ音乐雷达</div>
<div class="fm-desc">猜你喜欢 / 雷达推荐歌曲流</div>
</div>
<Icon icon="mdi:play-circle" class="fm-play-icon" />
</div>
</section>
<!-- 每日推荐 -->
@@ -126,8 +136,7 @@
<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue';
import { Icon } from '@iconify/vue';
import axios from 'axios';
import { usePlayerStore, type Song, type Source } from '../stores/player.js';
import { usePlayerStore, type Source } from '../stores/player.js';
import { loadTabSource, saveTabSource } from '../stores/sourceTabs.js';
import CoverArt from '../components/CoverArt.vue';
import SourceTabs from '../components/SourceTabs.vue';
@@ -180,19 +189,8 @@ const visibleUserPlaylists = computed(() =>
: currentUserPlaylists.value.slice(0, USER_PLAYLIST_LIMIT)
);
async function playFm() {
try {
const res = await axios.get('/api/music/personal/fm');
const songs: Song[] = res.data.songs;
if (songs.length > 0) {
await store.play(songs[0].name, songs[0].platform);
for (let i = 1; i < songs.length; i++) {
await store.addToQueue(songs[i].name, songs[i].platform);
}
}
} catch {
// Ignore
}
async function playFm(platform: Source) {
await store.startFm(platform);
}
onMounted(() => {
@@ -318,6 +316,7 @@ onMounted(() => {
border-radius: var(--radius-lg);
cursor: pointer;
transition: background var(--transition-fast);
margin-bottom: 12px;
&:hover {
background: var(--hover-bg);
@@ -333,6 +332,10 @@ onMounted(() => {
align-items: center;
justify-content: center;
flex-shrink: 0;
&.qq {
background: linear-gradient(135deg, var(--brand-qq), #17a2b8);
}
}
.fm-icon {