import { db } from '~/drizzle/db' import { expectedPlayDates, songs } from '~/drizzle/schema' import { eq, and } from 'drizzle-orm' export default defineEventHandler(async (event) => { const songId = Number(event.context.params?.id) const body = await readBody(event) if (!songId || isNaN(songId)) { throw createError({ statusCode: 400, message: '无效的歌曲ID' }) } // user check const user = event.context.user if (!user) { throw createError({ statusCode: 401, message: '需要登录' }) } const { expectedPlayDate, expectedPlaySequence } = body // 如果传空值,说明用户取消选择或清空 if (!expectedPlayDate || expectedPlaySequence === undefined) { await db.update(songs).set({ expectedPlayDate: null, expectedPlaySequence: null }).where(eq(songs.id, songId)) return { success: true } } try { // 开启事务检查冲突 const updatedSong = await db.transaction(async (tx) => { // 1. 检查日期和序号是否有效 const dateSetting = await tx.select().from(expectedPlayDates).where(eq(expectedPlayDates.date, expectedPlayDate)) if (dateSetting.length === 0 || !dateSetting[0].enabled) { throw createError({ statusCode: 400, message: '该日期未开放选座' }) } const availableSeqs = dateSetting[0].availableSequences.split(',').map(s => parseInt(s.trim(), 10)) if (!availableSeqs.includes(expectedPlaySequence)) { throw createError({ statusCode: 400, message: '无效的序号' }) } // 2. 检查是否已被占用 const takenSongs = await tx.select({ id: songs.id }) .from(songs) .where( and( eq(songs.expectedPlayDate, expectedPlayDate), eq(songs.expectedPlaySequence, expectedPlaySequence), eq(songs.played, false) ) ) if (takenSongs.length > 0 && takenSongs[0].id !== songId) { throw createError({ statusCode: 409, message: '该序号已被占用,请选择其他序号' }) } // 3. 更新歌曲 const result = await tx.update(songs).set({ expectedPlayDate, expectedPlaySequence }).where(and(eq(songs.id, songId), eq(songs.requesterId, user.id))).returning() if (result.length === 0) { throw createError({ statusCode: 404, message: '歌曲不存在或无权修改' }) } return result[0] }) return { success: true, data: updatedSong } } catch (error: any) { console.error('更新期望播出时段失败:', error) throw createError({ statusCode: error.statusCode || 500, message: error.message || '操作失败' }) } })