feat(deploy): production deployment setup and fixes

- Debian-based api image (bookworm-slim), docker/debian mirrors, prisma
  binaryTargets for openssl 3.0
- nginx: admin SPA under /admin, TLS via acme.sh (ZeroSSL) + auto-renewal
  cron, http->https redirect
- prisma: add origin_goods.delisted migration, sync missing schema
  (good_image/tag_font_color/good_tags), fix users.createdAt Timestamptz
- api: CORS wildcard reflection, helmet CORP cross-origin, price
  backfill in persistProductDetail, categoryIcon ancestor fallback,
  mediaByColor per-color gallery in public goods detail
- admin: /admin base path (vite + router)
- import-data.mjs: udt_name casting, serial sequence advance fix
This commit is contained in:
yeuimu
2026-08-26 14:23:09 +08:00
parent be0b90e68f
commit 6c61a4e871
982 changed files with 74156 additions and 179393 deletions
+56 -56
View File
@@ -1,57 +1,57 @@
import { ApiProperty } from '@nestjs/swagger';
import {
ArrayMinSize,
IsArray,
IsInt,
IsNotEmpty,
IsOptional,
IsString,
Min,
} from 'class-validator';
export class CreateGoodDto {
@ApiProperty()
@IsString()
@IsNotEmpty()
goodName!: string;
@ApiProperty()
@IsInt()
@Min(1)
originGoodId!: number;
@ApiProperty()
@IsInt()
@Min(1)
countryId!: number;
@ApiProperty()
@IsInt()
@Min(1)
categoryId!: number;
@ApiProperty({ required: false, nullable: true, type: [Number] })
@IsOptional()
@IsArray()
@ArrayMinSize(1)
@IsInt({ each: true })
@Min(1, { each: true })
tagIds?: number[];
@ApiProperty({ required: false, nullable: true })
@IsOptional()
@IsInt()
@Min(1)
positionId?: number;
@ApiProperty({ required: false, default: 0 })
@IsOptional()
@IsInt()
@Min(0)
goodPriority?: number;
@ApiProperty({ required: false, nullable: true })
@IsOptional()
@IsString()
goodImage?: string;
import { ApiProperty } from '@nestjs/swagger';
import {
ArrayMinSize,
IsArray,
IsInt,
IsNotEmpty,
IsOptional,
IsString,
Min,
} from 'class-validator';
export class CreateGoodDto {
@ApiProperty()
@IsString()
@IsNotEmpty()
goodName!: string;
@ApiProperty()
@IsInt()
@Min(1)
originGoodId!: number;
@ApiProperty()
@IsInt()
@Min(1)
countryId!: number;
@ApiProperty()
@IsInt()
@Min(1)
categoryId!: number;
@ApiProperty({ required: false, nullable: true, type: [Number] })
@IsOptional()
@IsArray()
@ArrayMinSize(1)
@IsInt({ each: true })
@Min(1, { each: true })
tagIds?: number[];
@ApiProperty({ required: false, nullable: true })
@IsOptional()
@IsInt()
@Min(1)
positionId?: number;
@ApiProperty({ required: false, default: 0 })
@IsOptional()
@IsInt()
@Min(0)
goodPriority?: number;
@ApiProperty({ required: false, nullable: true })
@IsOptional()
@IsString()
goodImage?: string;
}