127 lines
4.5 KiB
TypeScript
127 lines
4.5 KiB
TypeScript
import { db } from '~/drizzle/db'
|
|
import { cardCodeRedeemLogs, cardCodes, songs, users } from '~/drizzle/schema'
|
|
import { and, desc, eq, gte, ilike, lte, or } from 'drizzle-orm'
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
const user = event.context.user
|
|
if (!user) {
|
|
throw createError({ statusCode: 401, message: '未授权访问' })
|
|
}
|
|
if (!['SONG_ADMIN', 'ADMIN', 'SUPER_ADMIN'].includes(user.role)) {
|
|
throw createError({ statusCode: 403, message: '权限不足' })
|
|
}
|
|
|
|
try {
|
|
const query = getQuery(event)
|
|
const limitParam = Number(query.limit)
|
|
const limit = Number.isInteger(limitParam) ? Math.min(Math.max(limitParam, 1), 200) : 50
|
|
|
|
const keyword = typeof query.q === 'string' ? query.q.trim() : ''
|
|
const source = typeof query.source === 'string' ? query.source.trim().toUpperCase() : ''
|
|
const redeemer = typeof query.redeemer === 'string' ? query.redeemer.trim() : ''
|
|
const cardCode = typeof query.cardCode === 'string' ? query.cardCode.trim() : ''
|
|
const songKeyword = typeof query.song === 'string' ? query.song.trim() : ''
|
|
const startDate = typeof query.startDate === 'string' ? query.startDate.trim() : ''
|
|
const endDate = typeof query.endDate === 'string' ? query.endDate.trim() : ''
|
|
|
|
const conditions: any[] = []
|
|
|
|
if (source) {
|
|
conditions.push(eq(cardCodeRedeemLogs.source, source as any))
|
|
}
|
|
|
|
if (cardCode) {
|
|
conditions.push(or(ilike(cardCodes.code, `%${cardCode}%`), ilike(cardCodeRedeemLogs.codeSnapshot, `%${cardCode}%`)))
|
|
}
|
|
|
|
if (redeemer) {
|
|
conditions.push(or(ilike(users.name, `%${redeemer}%`), ilike(users.username, `%${redeemer}%`)))
|
|
}
|
|
|
|
if (songKeyword) {
|
|
conditions.push(or(ilike(songs.title, `%${songKeyword}%`), ilike(songs.artist, `%${songKeyword}%`)))
|
|
}
|
|
|
|
if (keyword) {
|
|
conditions.push(
|
|
or(
|
|
ilike(cardCodes.code, `%${keyword}%`),
|
|
ilike(cardCodeRedeemLogs.codeSnapshot, `%${keyword}%`),
|
|
ilike(users.name, `%${keyword}%`),
|
|
ilike(users.username, `%${keyword}%`),
|
|
ilike(songs.title, `%${keyword}%`),
|
|
ilike(songs.artist, `%${keyword}%`),
|
|
ilike(cardCodeRedeemLogs.source, `%${keyword}%`)
|
|
)
|
|
)
|
|
}
|
|
|
|
const startDateValue = startDate ? new Date(startDate) : null
|
|
if (startDateValue && !Number.isNaN(startDateValue.getTime())) {
|
|
conditions.push(gte(cardCodeRedeemLogs.redeemedAt, startDateValue))
|
|
}
|
|
|
|
const endDateValue = endDate ? new Date(endDate) : null
|
|
if (endDateValue && !Number.isNaN(endDateValue.getTime())) {
|
|
const adjustedEndDate = new Date(endDateValue)
|
|
adjustedEndDate.setHours(23, 59, 59, 999)
|
|
conditions.push(lte(cardCodeRedeemLogs.redeemedAt, adjustedEndDate))
|
|
}
|
|
|
|
let queryBuilder = db
|
|
.select({
|
|
id: cardCodeRedeemLogs.id,
|
|
cardCodeId: cardCodeRedeemLogs.cardCodeId,
|
|
codeSnapshot: cardCodeRedeemLogs.codeSnapshot,
|
|
redeemedAt: cardCodeRedeemLogs.redeemedAt,
|
|
source: cardCodeRedeemLogs.source,
|
|
songId: cardCodeRedeemLogs.songId,
|
|
currentCode: cardCodes.code,
|
|
songTitle: songs.title,
|
|
songArtist: songs.artist,
|
|
redeemerId: users.id,
|
|
redeemerName: users.name,
|
|
redeemerUsername: users.username
|
|
})
|
|
.from(cardCodeRedeemLogs)
|
|
.leftJoin(users, eq(cardCodeRedeemLogs.redeemedBy, users.id))
|
|
.leftJoin(cardCodes, eq(cardCodeRedeemLogs.cardCodeId, cardCodes.id))
|
|
.leftJoin(songs, eq(cardCodeRedeemLogs.songId, songs.id))
|
|
|
|
if (conditions.length > 0) {
|
|
queryBuilder = queryBuilder.where(and(...conditions))
|
|
}
|
|
|
|
const result = await queryBuilder
|
|
.orderBy(desc(cardCodeRedeemLogs.redeemedAt), desc(cardCodeRedeemLogs.id))
|
|
.limit(limit)
|
|
|
|
return {
|
|
success: true,
|
|
data: result.map((item) => ({
|
|
id: item.id,
|
|
cardCodeId: item.cardCodeId,
|
|
code: item.currentCode || item.codeSnapshot,
|
|
codeSnapshot: item.codeSnapshot,
|
|
redeemedAt: item.redeemedAt,
|
|
source: item.source,
|
|
song: item.songId
|
|
? {
|
|
id: item.songId,
|
|
title: item.songTitle || '未知歌曲',
|
|
artist: item.songArtist || ''
|
|
}
|
|
: null,
|
|
redeemer: {
|
|
id: item.redeemerId,
|
|
name: item.redeemerName || '未知用户',
|
|
username: item.redeemerUsername || 'unknown'
|
|
}
|
|
}))
|
|
}
|
|
} catch (err) {
|
|
console.error('获取点歌券兑换日志失败', err)
|
|
throw createError({ statusCode: 500, message: '获取点歌券兑换日志失败' })
|
|
}
|
|
})
|