lty/qy-lty-admin/lib/api/songs.ts
2026-03-17 13:17:02 +08:00

314 lines
9.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { Song } from "./types"
import { apiClient } from "./client"
import type { PaginatedResponse, PaginationParams } from "./client"
import {
CardSong,
CardSongResponse,
CardSongDetail,
CardSongDetailResponse,
SongBatch,
SongBatchesResponse,
CreateBatchRequest,
CreateBatchResponse,
MarkBatchAsProducedResponse,
CreateSongRequest,
UpdateSongRequest,
UploadSongFileResponse,
UploadSongFileRequest,
PublishSongResponse
} from "./song.type"
// 将API返回的歌曲数据转换为应用内使用的格式
export const transformCardSongToSong = (cardSong: CardSong): Song => {
return {
id: String(cardSong.id),
name: cardSong.name,
composer: cardSong.attributes.composer || "",
lyricist: cardSong.attributes.lyricist || "",
duration: cardSong.attributes.duration || "",
releaseDate: cardSong.published_at ? new Date(cardSong.published_at).toISOString().split('T')[0] : "",
status: cardSong.status_display,
image: cardSong.image_url || "/placeholder.svg?height=300&width=300",
audioUrl: cardSong.attributes.audio_file,
description: cardSong.description,
rarity: cardSong.rarity_display,
cardType: cardSong.card_type_display,
genre: cardSong.attributes.genre,
lyrics: cardSong.attributes.lyrics,
rawData: cardSong // 存储完整的原始数据
}
}
// 获取歌曲列表
export const getSongs = async (params?: PaginationParams): Promise<PaginatedResponse<Song>> => {
try {
const page = params?.page || 1;
const pageSize = params?.pageSize || 10;
const searchParam = params?.search ? `&search=${encodeURIComponent(params.search)}` : '';
const response = await apiClient.get(
`/card/category/song/?page_size=${pageSize}&page=${page}${searchParam}`
);
const data: CardSongResponse = response.data;
if (!data.success) {
throw new Error(data.message || '获取歌曲列表失败');
}
// 保存完整的歌曲数据,包括原始数据
const songs = data.data.results.map((item: any) => {
const attributes = item.attributes || {};
return {
id: String(item.id),
name: item.name,
composer: attributes.composer || '',
lyricist: attributes.lyricist || '',
duration: attributes.duration || '',
releaseDate: item.published_at ? new Date(item.published_at).toISOString().split('T')[0] : '',
status: item.status_display,
image: item.image_url || '/placeholder.svg?height=300&width=300',
audioUrl: attributes.audio_file || '',
description: item.description,
rarity: item.rarity_display,
cardType: item.card_type_display,
genre: attributes.genre,
lyrics: attributes.lyrics,
rawData: item // 存储完整的原始数据
};
});
return {
items: songs,
total: data.data.count,
page,
pageSize,
totalPages: Math.ceil(data.data.count / pageSize),
};
} catch (error) {
console.error('获取歌曲列表失败:', error);
throw error;
}
};
// 获取单个歌曲
export const getSong = async (id: string): Promise<Song> => {
try {
const response = await apiClient.get(`/card/templates/${id}/`);
const data: CardSongDetailResponse = response.data;
if (!data.success) {
throw new Error(data.message || '获取歌曲详情失败');
}
return transformCardSongDetailToSong(data.data);
} catch (error) {
console.error('获取歌曲详情失败:', error);
throw error;
}
};
// 将API返回的歌曲详情数据转换为应用内使用的格式
export const transformCardSongDetailToSong = (cardSong: CardSongDetail): Song => {
return {
id: String(cardSong.id),
name: cardSong.name,
composer: cardSong.attributes.composer || "",
lyricist: cardSong.attributes.lyricist || "",
duration: cardSong.attributes.duration || "",
releaseDate: cardSong.published_at ? new Date(cardSong.published_at).toISOString().split('T')[0] : "",
status: cardSong.status_display,
image: cardSong.image_url || "/placeholder.svg?height=300&width=300",
audioUrl: cardSong.attributes.audio_file,
description: cardSong.description,
rarity: cardSong.rarity_display,
cardType: cardSong.card_type_display,
genre: cardSong.attributes.genre,
lyrics: cardSong.attributes.lyrics,
price: cardSong.price,
batchesCount: cardSong.batches_count,
cardsCount: cardSong.active_cards_count,
createdAt: cardSong.created_at,
updatedAt: cardSong.updated_at,
rawData: cardSong // 存储完整的原始数据
}
}
// 创建歌曲
export const createSong = async (data: CreateSongRequest): Promise<any> => {
try {
const response = await apiClient.post('/card/templates/', data);
if (!response.data.success) {
throw new Error(response.data.message || '创建歌曲卡片模板失败');
}
return response.data.data;
} catch (error) {
console.error('创建歌曲失败:', error);
throw error;
}
};
// 更新歌曲
export const updateSong = async (id: string, data: UpdateSongRequest): Promise<any> => {
// 过滤空值
const filteredData = Object.entries(data).reduce((acc: any, [key, value]) => {
if (value !== null && value !== undefined && value !== '') {
if (key === 'song_attributes' && typeof value === 'object') {
// 过滤song_attributes中的空值
const filteredAttrs = Object.entries(value).reduce((attrAcc: any, [attrKey, attrValue]) => {
if (attrValue !== null && attrValue !== undefined && attrValue !== '') {
attrAcc[attrKey] = attrValue;
}
return attrAcc;
}, {});
// 只有当属性对象有内容时才添加
if (Object.keys(filteredAttrs).length > 0) {
acc[key] = filteredAttrs;
}
} else {
acc[key] = value;
}
}
return acc;
}, {});
try {
const response = await apiClient.put(`/card/templates/${id}/`, filteredData);
if (!response.data.success) {
throw new Error(response.data.message || '更新歌曲卡片模板失败');
}
return response.data.data;
} catch (error) {
console.error('更新歌曲失败:', error);
throw error;
}
};
// 删除歌曲
export const deleteSong = async (id: string): Promise<boolean> => {
try {
const response = await apiClient.delete(`/card/templates/${id}/`);
const data = response.data;
if (!data.success) {
throw new Error(data.message || '删除歌曲失败');
}
return true;
} catch (error) {
console.error('删除歌曲失败:', error);
throw error;
}
}
// 发布歌曲
export const publishSong = async (id: string): Promise<Song> => {
try {
const response = await apiClient.post(`/card/templates/${id}/publish/`);
const data: PublishSongResponse = response.data;
if (!data.success) {
throw new Error(data.message || '发布歌曲失败');
}
// 将返回的模板数据转换为Song类型
return transformCardSongDetailToSong(data.data.template);
} catch (error) {
console.error('发布歌曲失败:', error);
throw error;
}
};
// 获取歌曲批次数据
export const getSongBatches = async (songId: string): Promise<SongBatch[]> => {
try {
const response = await apiClient.get(`/card/batches/?template=${songId}`);
const data: SongBatchesResponse = response.data;
if (!data.success) {
throw new Error(data.message || '获取歌曲批次数据失败');
}
return data.data.results;
} catch (error) {
console.error('获取歌曲批次数据失败:', error);
throw error;
}
};
// 创建歌曲批次
export const createSongBatch = async (data: CreateBatchRequest): Promise<SongBatch> => {
try {
const response = await apiClient.post('/card/batches/generate/', data);
const responseData: CreateBatchResponse = response.data;
if (!responseData.success) {
throw new Error(responseData.message || '创建批次失败');
}
return responseData.data.batch;
} catch (error) {
console.error('创建批次失败:', error);
throw error;
}
};
// 将批次标记为已生产
export const markBatchAsProduced = async (batchId: number): Promise<SongBatch> => {
try {
const response = await apiClient.post(`/card/batches/${batchId}/mark_produced/`);
const responseData: MarkBatchAsProducedResponse = response.data;
if (!responseData.success) {
throw new Error(responseData.message || '标记批次为已生产失败');
}
return responseData.data.batch;
} catch (error) {
console.error('标记批次为已生产失败:', error);
throw error;
}
};
// 上传歌曲文件
export async function uploadSongFile(
params: UploadSongFileRequest
): Promise<UploadSongFileResponse> {
try {
const { file, isPermanent = true, filename } = params;
const formData = new FormData();
formData.append('file', file);
formData.append('is_permanent', isPermanent ? 'true' : 'false');
if (filename) formData.append('filename', filename);
const response = await apiClient.post('/common/upload/', formData, {
headers: {
// 使用multipart/form-data格式让axios自动设置正确的Content-Type和边界
'Content-Type': 'multipart/form-data'
}
});
const data = response.data;
if (!data.success) {
throw new Error(data.message || '上传文件失败');
}
return data.data;
} catch (error) {
console.error('上传文件失败:', error);
throw error;
}
}