diff --git a/app/components/Admin/KuGouImporter.client.vue b/app/components/Admin/KuGouImporter.client.vue index 6f87e1c..e2410c2 100644 --- a/app/components/Admin/KuGouImporter.client.vue +++ b/app/components/Admin/KuGouImporter.client.vue @@ -3,11 +3,38 @@

导入酷狗

- 绑定管理员酷狗账号后,可一键根据排期日期自动创建歌单并同步歌曲到酷狗歌单 + 支持两种方式:自动同步(sidecar 一键建歌单加歌)/ 手动生成照片卡片后扫码导入

-
+ +
+ + +
+ + +
@@ -395,6 +422,88 @@ PORT=3000 npm start
+ +
+
+
+

+ 选择日期 +

+ +
+
+ + +
+ + +
+
+
+ +
+ +
+ +

所选日期均没有排期歌曲

+
+
+ + +
@@ -403,6 +512,7 @@ import { computed, onMounted, ref, watch } from 'vue' import Icon from '~/components/UI/Icon.vue' import LoadingState from '~/components/UI/Common/LoadingState.vue' import AdminMultiDatePicker from './AdminMultiDatePicker.vue' +import AdminPlaylistCardGenerator from './PlaylistCardGenerator.vue' import { useAuth } from '~/composables/useAuth' import { useToast } from '~/composables/useToast' @@ -412,6 +522,8 @@ const toast = useToast() const WEEKDAY = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'] const today = new Date() const todayStr = `${today.getFullYear()}-${pad2(today.getMonth() + 1)}-${pad2(today.getDate())}` + +const mode = ref<'auto' | 'manual-card'>('auto') const selectedDates = ref([todayStr]) const status = ref(null) @@ -431,6 +543,13 @@ const baseUrlInput = ref('') const baseUrlSaving = ref(false) const baseUrlSavedTick = ref(0) +const cardSelectedDates = ref([todayStr]) +const cardSchedulesByDate = ref>({}) +const cardLoading = ref(false) +const showCardModal = ref(false) +const currentGeneratorDate = ref('') +const currentGeneratorSongs = ref([]) + const totalLoadedSongs = computed( () => Object.values(schedulesByDate.value).reduce((n, arr) => n + arr.length, 0), ) @@ -696,13 +815,62 @@ async function loadSyncHistory() { } } +async function fetchCardSchedulesForDate(date: string) { + try { + const response: any = await $fetch('/api/admin/schedule/full', { + ...auth.getAuthConfig(), + query: { date, includeDrafts: 'true' }, + }) + if (response?.success && response?.data?.schedules) { + return response.data.schedules + } + } catch (e: any) { + console.error(`Failed to fetch schedules for ${date}:`, e) + } + return [] +} + +async function fetchCardSchedules() { + if (cardSelectedDates.value.length === 0) { + cardSchedulesByDate.value = {} + return + } + cardLoading.value = true + const newSchedules: Record = {} + try { + const sortedDates = [...cardSelectedDates.value].sort() + for (const d of sortedDates) { + const items = await fetchCardSchedulesForDate(d) + if (items.length > 0) newSchedules[d] = items + } + cardSchedulesByDate.value = newSchedules + if (Object.keys(newSchedules).length === 0) { + toast.show?.('所选日期没有排期歌曲', 'info') + } + } catch (e: any) { + toast.show?.(e?.message || '获取排期失败', 'error') + } finally { + cardLoading.value = false + } +} + +function openGenerator(date: string, songs: any[]) { + currentGeneratorDate.value = date + currentGeneratorSongs.value = songs + showCardModal.value = true +} + watch( () => selectedDates.value.slice().sort().join(','), () => loadSchedules(), ) +watch( + () => cardSelectedDates.value.slice().sort().join(','), + () => fetchCardSchedules(), +) onMounted(async () => { await reloadStatus() - await Promise.all([loadSchedules(), loadSyncHistory()]) + await Promise.all([loadSchedules(), loadSyncHistory(), fetchCardSchedules()]) }) diff --git a/app/components/UI/Icon.vue b/app/components/UI/Icon.vue index ccf44d2..9090c46 100644 --- a/app/components/UI/Icon.vue +++ b/app/components/UI/Icon.vue @@ -399,6 +399,20 @@ + + + + + + + + + + + + + +