diff --git a/src/config/config.default.ts b/src/config/config.default.ts index 2d6fc59..423dc20 100644 --- a/src/config/config.default.ts +++ b/src/config/config.default.ts @@ -119,6 +119,15 @@ export default { description: 'Bearer Auth', addSecurityRequirements: true, }, + // 配置 Swagger 支持嵌套查询参数 + options: { + // 设置查询参数风格为 deepObject + // 这会告诉 Swagger 使用 JSON 格式来序列化嵌套的查询参数 + query: { + style: 'deepObject', + explode: false + } + } }, mailer: { host: 'smtphz.qiye.163.com', diff --git a/src/dto/api.dto.ts b/src/dto/api.dto.ts index 558048b..1388a4e 100644 --- a/src/dto/api.dto.ts +++ b/src/dto/api.dto.ts @@ -37,12 +37,16 @@ export class UnifiedSearchParamsDTO> { @ApiProperty({ description: '搜索关键词', required: false }) search?: string; - @ApiProperty({ description: '过滤条件对象', type: 'object', required: false }) + @ApiProperty({ + description: '过滤条件对象', + type: 'any', // FIXME 这里是因为 openapit2ts 会将 where 变成 undefined 所以有嵌套对象时先不指定类型 + required: false, + }) where?: Where; @ApiProperty({ description: '排序对象,例如 { "sku": "desc" }', - type: 'object', + type: 'any', // FIXME 这里是因为 openapit2ts 会将 where 变成 undefined 所以有嵌套对象时先不指定类型 required: false, }) orderBy?: Record | string; diff --git a/src/dto/product.dto.ts b/src/dto/product.dto.ts index 1feccfe..dfb794b 100644 --- a/src/dto/product.dto.ts +++ b/src/dto/product.dto.ts @@ -303,6 +303,68 @@ export interface ProductWhereFilter { updatedAtEnd?: string; } +/** + * 产品查询过滤条件DTO + */ +export class ProductWhereFilterDTO { + @ApiProperty({ description: '产品ID', example: 1 }) + id?: number; + + @ApiProperty({ description: '产品ID列表', example: [1, 2, 3] }) + ids?: number[]; + + @ApiProperty({ description: 'SKU', example: 'ZYN-6MG-WINTERGREEN' }) + sku?: string; + + @ApiProperty({ description: 'SKU列表', example: ['ZYN-6MG-WINTERGREEN', 'ZYN-3MG-WINTERGREEN'] }) + skus?: string[]; + + @ApiProperty({ description: '产品名称', example: 'ZYN 6MG WINTERGREEN' }) + name?: string; + + @ApiProperty({ description: '产品中文名称', example: 'ZYN 6毫克 冬清味' }) + nameCn?: string; + + @ApiProperty({ description: '分类ID', example: 1 }) + categoryId?: number; + + @ApiProperty({ description: '分类ID列表', example: [1, 2, 3] }) + categoryIds?: number[]; + + @ApiProperty({ description: '品牌ID', example: 1 }) + brandId?: number; + + @ApiProperty({ description: '品牌ID列表', example: [1, 2, 3] }) + brandIds?: number[]; + + @ApiProperty({ description: '产品类型', example: 'single', enum: ['single', 'bundle'] }) + type?: string; + + @ApiProperty({ description: '价格最小值', example: 99.99 }) + minPrice?: number; + + @ApiProperty({ description: '价格最大值', example: 199.99 }) + maxPrice?: number; + + @ApiProperty({ description: '促销价格最小值', example: 89.99 }) + minPromotionPrice?: number; + + @ApiProperty({ description: '促销价格最大值', example: 179.99 }) + maxPromotionPrice?: number; + + @ApiProperty({ description: '创建时间范围开始', example: '2023-01-01 00:00:00' }) + createdAtStart?: string; + + @ApiProperty({ description: '创建时间范围结束', example: '2023-12-31 23:59:59' }) + createdAtEnd?: string; + + @ApiProperty({ description: '更新时间范围开始', example: '2023-01-01 00:00:00' }) + updatedAtStart?: string; + + @ApiProperty({ description: '更新时间范围结束', example: '2023-12-31 23:59:59' }) + updatedAtEnd?: string; +} + /** * DTO 用于分页查询产品 * 支持灵活的where条件、分页和排序 diff --git a/src/entity/product.entity.ts b/src/entity/product.entity.ts index 8b117d7..ea763ec 100644 --- a/src/entity/product.entity.ts +++ b/src/entity/product.entity.ts @@ -37,7 +37,7 @@ export class Product { @ApiProperty({ example: 'ZYN 6MG WINTERGREEN', description: '产品名称', - type: 'string', + type: 'string', required: true, }) @Column() diff --git a/src/service/product.service.ts b/src/service/product.service.ts index 1a06051..bbde5d9 100644 --- a/src/service/product.service.ts +++ b/src/service/product.service.ts @@ -235,7 +235,6 @@ export class ProductService { .leftJoinAndSelect('product.attributes', 'attribute') .leftJoinAndSelect('attribute.dict', 'dict') .leftJoinAndSelect('product.category', 'category'); - // 处理分页参数(支持新旧两种格式) const page = query.page || 1; const pageSize = query.per_page || 10;