Files
wxmp_backend/src/design-list/dto/create-design-list.dto.ts
T
lhmin0604andClaude 0a3c8e834d feat(r2): 地址与设计清单完整 CRUD(事务/归属校验/状态机)
addresses:
- 补 PATCH /:id、DELETE /:id(契约 §4 全路由齐备)
- 默认地址唯一性事务:create/update/setDefault 先清旧默认再写入
- 首个地址自动设为默认;删除默认地址事务内补偿最新一条
- 归属校验统一:不存在 404,非本人 403

design-list:
- 补 PATCH /:id、DELETE /:id、POST /batch-delete(宽松语义返回 deleted 数)
- items 强制恰好 1 个元素(一条设计=一条清单,阶段0 决策#1)
- designData 白名单 7 键放行、单条 ≤1MB 校验(400)
- 单向状态机 DRAFT→SUBMITTED→PROCESSING→DONE,回退/跳级 400
- PATCH 部分更新语义,不传 items 不清 designData(R4 wordcloud 保护)

infra:
- main.ts: JSON body 上限 100KB→2MB,使契约 1MB 设计数据可达(>2MB 返回 413)
- exceptions filter: body-parser entity.too.large 映射 413
- api-contract-v1.md §5 补实现说明(非契约变更)

验证:nest build 通过;本地 3091 实例 + mock 登录实测 35 项全过
(CRUD/默认地址补偿/越权 403/404/状态机/1MB 边界/413/未登录 401)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-12 02:37:53 +08:00

65 lines
1.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import {
ArrayMaxSize,
ArrayMinSize,
IsArray,
IsNotEmpty,
IsNumber,
IsObject,
IsOptional,
IsString,
Max,
Min,
ValidateNested,
} from 'class-validator';
/**
* 清单条目(api-contract-v1 §5)。
* 阶段0 决策#1:一条前端 DesignItem = 一条后端 DesignListitems 固定 1 个元素;
* 决策#3productIcon 不入库,由客户端按 productId 推导。
*/
export class DesignListEntryDto {
@ApiProperty()
@IsString()
@IsNotEmpty()
productId!: string;
@ApiProperty()
@IsString()
@IsNotEmpty()
productName!: string;
@ApiProperty()
@IsNumber()
@Min(0)
unitPrice!: number;
@ApiProperty()
@IsNumber()
@Min(1)
@Max(999)
count!: number;
/** 结构白名单与大小校验在 service 层做(设计数据契约 v1 */
@ApiPropertyOptional()
@IsOptional()
@IsObject()
designData?: Record<string, unknown>;
}
export class CreateDesignListDto {
@ApiProperty({ description: '清单标题;前端传 productName(阶段0 决策#4' })
@IsString()
@IsNotEmpty()
title!: string;
@ApiProperty({ type: [DesignListEntryDto] })
@IsArray()
@ArrayMinSize(1)
@ArrayMaxSize(1)
@ValidateNested({ each: true })
@Type(() => DesignListEntryDto)
items!: DesignListEntryDto[];
}