feat(web): T-WEB-003 /api/songs CRUD + 音频上传

This commit is contained in:
2026-09-14 19:00:55 +08:00
parent 6714b1e67c
commit d9614aadb0
10 changed files with 907 additions and 0 deletions
+56
View File
@@ -0,0 +1,56 @@
import { BadRequestException, NotFoundException } from '@nestjs/common';
import { extname } from 'node:path';
/** 上传文件的最小信息(兼容 multer 的 Express.Multer.File 与测试替身) */
export interface UploadedFileLike {
originalname: string;
mimetype: string;
path: string;
size: number;
}
export function requireUploadedFile(file: UploadedFileLike | undefined, label = 'file'): UploadedFileLike {
if (!file) throw new BadRequestException(`缺少上传文件字段 ${label}`);
if (!file.path) throw new BadRequestException('上传文件未落盘');
return file;
}
/** 按扩展名白名单解析格式;不在白名单内一律 422 */
export function resolveFormatByExtension(
originalName: string,
map: Record<string, string>,
kindLabel: string,
): { ext: string; format: string } {
const ext = extname(originalName).toLowerCase();
const format = map[ext];
if (!format) {
throw new BadRequestException(
`${kindLabel}格式不支持:${ext || '(无扩展名)'},允许:${Object.keys(map).join(', ')}`,
);
}
return { ext, format };
}
export function parseOptionalInt(value: unknown, field: string): number | undefined {
if (value === undefined || value === null || value === '') return undefined;
const num = Number(value);
if (!Number.isFinite(num)) throw new BadRequestException(`${field} 必须为数字`);
return Math.trunc(num);
}
export function parseOptionalNumber(value: unknown, field: string): number | undefined {
if (value === undefined || value === null || value === '') return undefined;
const num = Number(value);
if (!Number.isFinite(num)) throw new BadRequestException(`${field} 必须为数字`);
return num;
}
export function parseOptionalBool(value: unknown): boolean {
if (value === undefined || value === null || value === '') return false;
if (typeof value === 'boolean') return value;
return value === 'true' || value === '1' || value === 1;
}
export function notFound(what: string, id: number | string): NotFoundException {
return new NotFoundException(`${what} #${id} 不存在`);
}