feat: 完成分类、worksheet 接口开发,资源迁移到七牛
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
import { BadRequestException } from '@nestjs/common';
|
||||
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||
import { Allow } from 'class-validator';
|
||||
import type {
|
||||
ContentStatus,
|
||||
UpdateContentStatusRequest,
|
||||
} from '@doodle/contracts';
|
||||
import {
|
||||
WorksheetQueryDto,
|
||||
parseWorksheetQuery,
|
||||
} from '../worksheets/worksheet-query.dto';
|
||||
import { contentStatus } from './content-policy';
|
||||
|
||||
/** 管理列表才接受 status;公开接口不复用此 DTO,避免开放草稿查询开关。 */
|
||||
export class AdminWorksheetQueryDto extends WorksheetQueryDto {
|
||||
@Allow()
|
||||
@ApiPropertyOptional({
|
||||
enum: ['draft', 'active', 'hidden'],
|
||||
description: '省略查询全部状态',
|
||||
})
|
||||
declare status?: string;
|
||||
}
|
||||
|
||||
/** 首期只提供状态写入,不开放未经白名单校验的渲染配置编辑。 */
|
||||
export class UpdateContentStatusDto implements UpdateContentStatusRequest {
|
||||
@Allow()
|
||||
@ApiProperty({ enum: ['draft', 'active', 'hidden'] })
|
||||
declare status: ContentStatus;
|
||||
}
|
||||
|
||||
/** 资源管理列表仅支持分页、所属题型和状态,不隐式套用题型年龄/年级条件。 */
|
||||
export class AdminResourceQueryDto {
|
||||
@Allow()
|
||||
@ApiPropertyOptional({
|
||||
type: 'integer',
|
||||
default: 1,
|
||||
minimum: 1,
|
||||
maximum: 1000000,
|
||||
})
|
||||
declare page?: string;
|
||||
|
||||
@Allow()
|
||||
@ApiPropertyOptional({
|
||||
type: 'integer',
|
||||
default: 20,
|
||||
minimum: 1,
|
||||
maximum: 100,
|
||||
})
|
||||
declare pageSize?: string;
|
||||
|
||||
@Allow()
|
||||
@ApiPropertyOptional({ maxLength: 128 })
|
||||
declare worksheetId?: string;
|
||||
|
||||
@Allow()
|
||||
@ApiPropertyOptional({ enum: ['draft', 'active', 'hidden'] })
|
||||
declare status?: string;
|
||||
}
|
||||
|
||||
/** 服务层同样检查字段白名单,防止非 HTTP 调用绕过状态参数限制。 */
|
||||
export function parseAdminWorksheetQuery(input: AdminWorksheetQueryDto) {
|
||||
const { status, ...query } = input;
|
||||
return {
|
||||
query: parseWorksheetQuery(query),
|
||||
status: status === undefined ? undefined : contentStatus(status),
|
||||
};
|
||||
}
|
||||
|
||||
/** 严格解析资源分页和过滤;拒绝重复/未知字段,避免管理查询静默扩大范围。 */
|
||||
export function parseAdminResourceQuery(input: AdminResourceQueryDto) {
|
||||
if (
|
||||
Object.keys(input).some(
|
||||
(key) =>
|
||||
!['page', 'pageSize', 'worksheetId', 'status'].includes(key),
|
||||
)
|
||||
)
|
||||
throw new BadRequestException();
|
||||
const { page, pageSize } = parseWorksheetQuery({
|
||||
...(input.page === undefined ? {} : { page: input.page }),
|
||||
...(input.pageSize === undefined ? {} : { pageSize: input.pageSize }),
|
||||
});
|
||||
const worksheetId = input.worksheetId;
|
||||
if (
|
||||
worksheetId !== undefined &&
|
||||
(typeof worksheetId !== 'string' ||
|
||||
!worksheetId.trim() ||
|
||||
[...worksheetId].length > 128 ||
|
||||
worksheetId.includes('\0'))
|
||||
)
|
||||
throw new BadRequestException();
|
||||
return {
|
||||
page,
|
||||
pageSize,
|
||||
worksheetId,
|
||||
status:
|
||||
input.status === undefined
|
||||
? undefined
|
||||
: contentStatus(input.status),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user