import { ApiProperty } from '@midwayjs/swagger'; import { Rule, RuleType } from '@midwayjs/validate'; import { UnifiedSearchParamsDTO } from './api.dto'; /** * 属性输入DTO */ export class AttributeInputDTO { @ApiProperty({ description: '属性字典标识', example: 'brand' }) @Rule(RuleType.string()) dictName?: string; @ApiProperty({ description: '属性值', example: 'ZYN' }) @Rule(RuleType.string()) value?: string; @ApiProperty({ description: '属性ID', example: 1 }) @Rule(RuleType.number()) id?: number; @ApiProperty({ description: '属性名称', example: 'ZYN' }) @Rule(RuleType.string()) name?: string; @ApiProperty({ description: '属性显示名称', example: 'ZYN' }) @Rule(RuleType.string()) title?: string; } /** * DTO 用于创建产品 */ export class CreateProductDTO { @ApiProperty({ example: 'ZYN 6MG WINTERGREEN', description: '产品名称', required: true, }) @Rule(RuleType.string().required().empty({ message: '产品名称不能为空' })) name: string; @ApiProperty({ description: '产品中文名称', required: false }) @Rule(RuleType.string().allow('').optional()) nameCn?: string; @ApiProperty({ example: '产品描述', description: '产品描述' }) @Rule(RuleType.string()) description: string; @ApiProperty({ example: '产品简短描述', description: '产品简短描述' }) @Rule(RuleType.string().optional()) shortDescription?: string; @ApiProperty({ description: '产品 SKU', required: false }) @Rule(RuleType.string()) sku?: string; @ApiProperty({ description: '分类ID (DictItem ID)', required: false }) @Rule(RuleType.number()) categoryId?: number; @ApiProperty({ description: '分类名称', required: false }) @Rule(RuleType.string().optional()) categoryName?: string; @ApiProperty({ description: '站点 SKU 列表', type: 'array', required: false }) @Rule(RuleType.array().items(RuleType.string()).optional()) siteSkus?: string[]; // 通用属性输入(通过 attributes 统一提交品牌/口味/强度/尺寸/干湿等) // 当 type 为 'single' 时必填,当 type 为 'bundle' 时可选 @ApiProperty({ description: '属性列表', type: 'array', required: false }) @Rule( RuleType.array() .when('type', { is: 'single', then: RuleType.array().required(), otherwise: RuleType.array().optional() }) ) attributes?: AttributeInputDTO[]; // 商品价格 @ApiProperty({ description: '价格', example: 99.99, required: false }) @Rule(RuleType.number()) price?: number; // 促销价格 @ApiProperty({ description: '促销价格', example: 99.99, required: false }) @Rule(RuleType.number()) promotionPrice?: number; // 产品图片URL @ApiProperty({ description: '产品图片URL', example: 'https://example.com/image.jpg', required: false }) @Rule(RuleType.string().optional()) image?: string; // 商品类型(默认 single; bundle 需手动设置组成) @ApiProperty({ description: '商品类型', enum: ['single', 'bundle'], default: 'single', required: false }) @Rule(RuleType.string().valid('single', 'bundle').default('single')) type?: string; // 仅当 type 为 'bundle' 时,才需要提供 components @ApiProperty({ description: '产品组成', type: 'array', required: false }) @Rule( RuleType.array() .items( RuleType.object({ sku: RuleType.string().required(), quantity: RuleType.number().required(), }) ) .when('type', { is: 'bundle', then: RuleType.array().required(), }) ) components?: { sku: string; quantity: number }[]; } /** * DTO 用于更新产品 */ export class UpdateProductDTO { @ApiProperty({ example: 'ZYN 6MG WINTERGREEN', description: '产品名称' }) @Rule(RuleType.string()) name?: string; @ApiProperty({ description: '产品中文名称', required: false }) @Rule(RuleType.string().allow('').optional()) nameCn?: string; @ApiProperty({ example: '产品描述', description: '产品描述' }) @Rule(RuleType.string()) description?: string; @ApiProperty({ example: '产品简短描述', description: '产品简短描述' }) @Rule(RuleType.string().optional()) shortDescription?: string; @ApiProperty({ description: '产品 SKU', required: false }) @Rule(RuleType.string()) sku?: string; @ApiProperty({ description: '分类ID (DictItem ID)', required: false }) @Rule(RuleType.number()) categoryId?: number; @ApiProperty({ description: '分类名称', required: false }) @Rule(RuleType.string().optional()) categoryName?: string; @ApiProperty({ description: '站点 SKU 列表', type: 'array', required: false }) @Rule(RuleType.array().items(RuleType.string()).optional()) siteSkus?: string[]; // 商品价格 @ApiProperty({ description: '价格', example: 99.99, required: false }) @Rule(RuleType.number()) price?: number; // 促销价格 @ApiProperty({ description: '促销价格', example: 99.99, required: false }) @Rule(RuleType.number()) promotionPrice?: number; // 产品图片URL @ApiProperty({ description: '产品图片URL', example: 'https://example.com/image.jpg', required: false }) @Rule(RuleType.string().optional()) image?: string; // 属性更新(可选, 支持增量替换指定字典的属性项) @ApiProperty({ description: '属性列表', type: 'array', required: false }) @Rule(RuleType.array()) attributes?: AttributeInputDTO[]; // 商品类型(single 或 bundle) @ApiProperty({ description: '商品类型', enum: ['single', 'bundle'], required: false }) @Rule(RuleType.string().valid('single', 'bundle')) type?: string; // 仅当 type 为 'bundle' 时,才需要提供 components @ApiProperty({ description: '产品组成', type: 'array', required: false }) @Rule( RuleType.array() .items( RuleType.object({ sku: RuleType.string().required(), quantity: RuleType.number().required(), }) ) .when('type', { is: 'bundle', then: RuleType.array().optional(), }) ) components?: { sku: string; quantity: number }[]; } /** * DTO 用于批量更新产品属性 */ export class BatchUpdateProductDTO { @ApiProperty({ description: '产品ID列表', type: 'array', required: true }) @Rule(RuleType.array().items(RuleType.number()).required().min(1)) ids: number[]; @ApiProperty({ example: 'ZYN 6MG WINTERGREEN', description: '产品名称', required: false }) @Rule(RuleType.string().optional()) name?: string; @ApiProperty({ description: '产品中文名称', required: false }) @Rule(RuleType.string().allow('').optional()) nameCn?: string; @ApiProperty({ example: '产品描述', description: '产品描述', required: false }) @Rule(RuleType.string().optional()) description?: string; @ApiProperty({ example: '产品简短描述', description: '产品简短描述', required: false }) @Rule(RuleType.string().optional()) shortDescription?: string; @ApiProperty({ description: '产品 SKU', required: false }) @Rule(RuleType.string().optional()) sku?: string; @ApiProperty({ description: '分类ID (DictItem ID)', required: false }) @Rule(RuleType.number().optional()) categoryId?: number; @ApiProperty({ description: '站点 SKU 列表', type: 'array', required: false }) @Rule(RuleType.array().items(RuleType.string()).optional()) siteSkus?: string[]; @ApiProperty({ description: '价格', example: 99.99, required: false }) @Rule(RuleType.number().optional()) price?: number; @ApiProperty({ description: '促销价格', example: 99.99, required: false }) @Rule(RuleType.number().optional()) promotionPrice?: number; @ApiProperty({ description: '产品图片URL', example: 'https://example.com/image.jpg', required: false }) @Rule(RuleType.string().optional()) image?: string; @ApiProperty({ description: '属性列表', type: 'array', required: false }) @Rule(RuleType.array().optional()) attributes?: AttributeInputDTO[]; @ApiProperty({ description: '商品类型', enum: ['single', 'bundle'], required: false }) @Rule(RuleType.string().valid('single', 'bundle').optional()) type?: string; } /** * DTO 用于批量删除产品 */ export class BatchDeleteProductDTO { @ApiProperty({ description: '产品ID列表', type: 'array', required: true }) @Rule(RuleType.array().items(RuleType.number()).required().min(1)) ids: number[]; } /** * DTO 用于创建分类属性绑定 */ export class CreateCategoryAttributeDTO { @ApiProperty({ description: '分类字典项ID', example: 1 }) @Rule(RuleType.number().required()) categoryItemId: number; @ApiProperty({ description: '属性字典ID列表', example: [2, 3] }) @Rule(RuleType.array().items(RuleType.number()).required()) attributeDictIds: number[]; } /** * 产品查询过滤条件接口 */ export interface ProductWhereFilter { // 产品ID id?: number; // 产品ID列表 ids?: number[]; // SKU sku?: string; // SKU列表 skus?: string[]; // 产品名称 name?: string; // 产品中文名称 nameCn?: string; // 分类ID categoryId?: number; // 分类ID列表 categoryIds?: number[]; // 品牌ID brandId?: number; // 品牌ID列表 brandIds?: number[]; // 产品类型 type?: string; // 价格最小值 minPrice?: number; // 价格最大值 maxPrice?: number; // 促销价格最小值 minPromotionPrice?: number; // 促销价格最大值 maxPromotionPrice?: number; // 创建时间范围开始 createdAtStart?: string; // 创建时间范围结束 createdAtEnd?: string; // 更新时间范围开始 updatedAtStart?: string; // 更新时间范围结束 updatedAtEnd?: string; // TODO 使用 attributes 过滤 attributes?: Record; } /** * 产品查询过滤条件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条件、分页和排序 */ export class QueryProductDTO extends UnifiedSearchParamsDTO { } /** * DTO 用于创建分类 */ export class CreateCategoryDTO { @ApiProperty({ description: '分类显示名称', required: true }) @Rule(RuleType.string().required()) title: string; @ApiProperty({ description: '分类中文名称', required: false }) @Rule(RuleType.string().allow('').optional()) titleCN?: string; @ApiProperty({ description: '分类唯一标识', required: true }) @Rule(RuleType.string().required()) name: string; @ApiProperty({ description: '分类短名称,用于生成SKU', required: false }) @Rule(RuleType.string().allow('').optional()) shortName?: string; @ApiProperty({ description: '排序', required: false }) @Rule(RuleType.number().optional()) sort?: number; } /** * DTO 用于更新分类 */ export class UpdateCategoryDTO { @ApiProperty({ description: '分类显示名称', required: false }) @Rule(RuleType.string().optional()) title?: string; @ApiProperty({ description: '分类中文名称', required: false }) @Rule(RuleType.string().allow('').optional()) titleCN?: string; @ApiProperty({ description: '分类唯一标识', required: false }) @Rule(RuleType.string().optional()) name?: string; @ApiProperty({ description: '分类短名称,用于生成SKU', required: false }) @Rule(RuleType.string().allow('').optional()) shortName?: string; @ApiProperty({ description: '排序', required: false }) @Rule(RuleType.number().optional()) sort?: number; }