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
+41
View File
@@ -0,0 +1,41 @@
import { Type } from 'class-transformer';
import { IsInt, IsOptional, Max, Min } from 'class-validator';
/** 契约 data-models.md §1:列表接口统一分页参数 */
export class PageQueryDto {
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(1)
page: number = 1;
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(1)
@Max(200)
pageSize: number = 20;
get skip(): number {
return (this.page - 1) * this.pageSize;
}
}
export interface Paged<T> {
items: T[];
total: number;
page: number;
pageSize: number;
}
export function toPaged<T>(items: T[], total: number, query: { page: number; pageSize: number }): Paged<T> {
return { items, total, page: query.page, pageSize: query.pageSize };
}
/** 规范化分页参数(用于非 DTO 校验路径,如内部调用) */
export function normalizePaging(page?: number, pageSize?: number, maxPageSize = 200): { page: number; pageSize: number; skip: number } {
const p = Number.isFinite(page) && (page as number) >= 1 ? Math.floor(page as number) : 1;
const rawSize = Number.isFinite(pageSize) ? Math.floor(pageSize as number) : 20;
const size = Math.min(Math.max(rawSize, 1), maxPageSize);
return { page: p, pageSize: size, skip: (p - 1) * size };
}