diff --git a/app/components/Admin/ScheduleManager.vue b/app/components/Admin/ScheduleManager.vue index dada685..d05136a 100644 --- a/app/components/Admin/ScheduleManager.vue +++ b/app/components/Admin/ScheduleManager.vue @@ -741,6 +741,15 @@ + + + + { try { - // 如果列表为空,提示删除排期 if (localScheduledSongs.value.length === 0) { - confirmDialogTitle.value = '删除排期' - confirmDialogMessage.value = '确定要删除当天的所有排期吗?此操作不可恢复。' - confirmDialogType.value = 'danger' - confirmDialogConfirmText.value = '确认删除' - } else { - confirmDialogTitle.value = '发布排期' - confirmDialogMessage.value = '确定要发布当前排期吗?发布后将立即公示并发送通知。' - confirmDialogType.value = 'warning' - confirmDialogConfirmText.value = '发布排期' + showToast('当前列表没有歌曲,没有需要发布的内容', 'info') + return } + confirmDialogTitle.value = '发布排期' + confirmDialogMessage.value = '确定要发布当前排期吗?发布后将立即公示并发送通知。' + confirmDialogType.value = 'warning' + confirmDialogConfirmText.value = '发布排期' + confirmAction.value = async () => { await publishScheduleConfirmed() } @@ -2528,6 +2543,56 @@ const publishSchedule = async () => { } } +/** + * 清空当天的排期(含草稿)—— 独立的显式操作,跟「发布」彻底分开。 + * 服务端 bulk-publish 收到空 songs 数组时会先删该日期全部排期再插入 0 条(即清空), + * 所以「删除」这个破坏性动作必须由调用方明确要求,见 bulk-publish.post.ts 里的 confirmClear。 + */ +const clearTodaySchedule = () => { + if (localScheduledSongs.value.length === 0) { + showToast('当天本来就没有排期', 'info') + return + } + + confirmDialogTitle.value = '删除当天排期' + confirmDialogMessage.value = `确定要删除 ${selectedDate.value} 的全部排期吗?已发布的排期和草稿都会一起删除,此操作不可恢复。` + confirmDialogType.value = 'danger' + confirmDialogConfirmText.value = '确认删除' + + confirmAction.value = async () => { + loading.value = true + try { + await $fetch('/api/admin/schedule/bulk-publish', { + method: 'POST', + body: { + playDate: selectedDate.value, + playTimeId: selectedPlayTime.value ? parseInt(selectedPlayTime.value) : null, + songs: [], + confirmClear: true // 明确表示「我就是要清空」,缺了它服务端会拒(防止误清) + }, + ...auth.getAuthConfig() + }) + + hasChanges.value = false + await loadData() + updateLocalScheduledSongs() + + if (window.$showNotification) { + window.$showNotification('当天排期已删除', 'success') + } + } catch (error) { + console.error('删除当天排期失败:', error) + if (window.$showNotification) { + window.$showNotification('删除失败: ' + (error.data?.message || error.message), 'error') + } + } finally { + loading.value = false + } + } + + showConfirmDialog.value = true +} + // 确认发布排期 const publishScheduleConfirmed = async () => { loading.value = true diff --git a/server/api/admin/schedule/bulk-publish.post.ts b/server/api/admin/schedule/bulk-publish.post.ts index 0235148..2a91ad9 100644 --- a/server/api/admin/schedule/bulk-publish.post.ts +++ b/server/api/admin/schedule/bulk-publish.post.ts @@ -48,8 +48,16 @@ export default defineEventHandler(async (event) => { // 获取所有涉及的歌曲详情(用于通知) const songIds = body.songs.map((s: any) => s.songId) - if (songIds.length === 0) { - // 如果列表为空,说明是清空排期,直接执行删除逻辑即可 + /* + * ⚠️ 空 songs = 「清空该日期排期」:下面第 3 步会先删光该日期(含草稿)的排期,再插入 0 条。 + * 这是个**破坏性操作**,绝不能因为前端列表没加载出来(数组恰好是空)就被误触发 —— + * 以前点「发布」就能把一整天删掉。所以清空必须由调用方显式带 confirmClear: true。 + */ + if (songIds.length === 0 && body.confirmClear !== true) { + throw createError({ + statusCode: 400, + message: '歌曲列表为空:发布需要至少一首歌;若要清空当天排期,请显式传 confirmClear: true' + }) } const songDetails =