Files
inkreach-official-website/inkreach-official-nestjs/src/goods/dto/good.dto.ts
T
yeuimu a903dd4903 feat(admin): redesign GoodsView with dual-tree UX, filter bar, inline CRUD
- Two-line good nodes with country + tag chips, hover tooltip
- Resizable dual-tree with fixed-height panels (no node overlap)
- Filter bar: search, country filter, tag filter (multi-select with rename)
- Mode switch (品类/国家) pushed to right via spacer
- Inline create country/tag in edit & config modals via quick-create buttons
- Right tree node height auto-fix for locate highlight
- Filter dropdown styles in global scope for teleported popper
- Backend: multi-tag (GoodTag junction), goodImage column, origin goods tree API
- Admin response interceptor unwraps {data, success} envelope
- Simplified sidebar to single 商品管理 entry with tabs
- SyncView simplified to product sync only
2026-06-22 01:47:20 +08:00

149 lines
4.2 KiB
TypeScript

import { ApiProperty } from '@nestjs/swagger';
import type { Good as PrismaGood } from '@prisma/client';
export interface GoodRelations {
country?: { id: bigint; countryName: string; countryIcon: string | null } | null;
category?: { id: bigint; categoryName: string; categoryIcon: string | null } | null;
tag?: { id: bigint; tagName: string; tagColor: string | null } | null;
position?: { id: bigint; indexVal: number } | null;
originGood?: {
id: bigint;
sdsGoodId: string;
goodName: string | null;
goodImage: string | null;
goodPrice: unknown;
} | null;
goodTags?: { tag: { id: bigint; tagName: string; tagColor: string | null } }[];
}
export class GoodDto {
@ApiProperty()
id!: string;
@ApiProperty()
goodName!: string;
@ApiProperty({ nullable: true })
goodImage!: string | null;
@ApiProperty()
goodPriority!: number;
@ApiProperty()
countryId!: string;
@ApiProperty()
categoryId!: string;
@ApiProperty({ nullable: true })
tagId!: string | null;
@ApiProperty({ nullable: true })
positionId!: string | null;
@ApiProperty()
originGoodId!: string;
@ApiProperty()
createdAt!: string;
@ApiProperty()
updatedAt!: string;
@ApiProperty({ required: false, nullable: true })
country?: { id: string; countryName: string; countryIcon: string | null } | null;
@ApiProperty({ required: false, nullable: true })
category?: { id: string; categoryName: string; categoryIcon: string | null } | null;
@ApiProperty({ required: false, nullable: true })
tag?: { id: string; tagName: string; tagColor: string | null } | null;
@ApiProperty({ required: false, type: Array })
tags!: Array<{ id: string; tagName: string; tagColor: string | null }>;
@ApiProperty({ required: false, nullable: true })
position?: { id: string; indexVal: number } | null;
@ApiProperty({ required: false, nullable: true })
originGood?: {
id: string;
sdsGoodId: string;
goodName: string | null;
goodImage: string | null;
goodPrice: string | null;
} | null;
static from(
good: PrismaGood,
rel: GoodRelations = {},
): GoodDto {
return {
id: good.id.toString(),
goodName: good.goodName,
goodImage: good.goodImage,
goodPriority: good.goodPriority,
countryId: good.countryId.toString(),
categoryId: good.categoryId.toString(),
tagId: good.tagId === null || good.tagId === undefined ? null : good.tagId.toString(),
positionId: good.positionId === null || good.positionId === undefined ? null : good.positionId.toString(),
originGoodId: good.originGoodId.toString(),
createdAt: good.createdAt.toISOString(),
updatedAt: good.updatedAt.toISOString(),
country: rel.country
? {
id: rel.country.id.toString(),
countryName: rel.country.countryName,
countryIcon: rel.country.countryIcon,
}
: null,
category: rel.category
? {
id: rel.category.id.toString(),
categoryName: rel.category.categoryName,
categoryIcon: rel.category.categoryIcon,
}
: null,
tag: rel.tag
? {
id: rel.tag.id.toString(),
tagName: rel.tag.tagName,
tagColor: rel.tag.tagColor,
}
: null,
tags: rel.goodTags
? rel.goodTags.map((gt) => ({
id: gt.tag.id.toString(),
tagName: gt.tag.tagName,
tagColor: gt.tag.tagColor,
}))
: [],
position: rel.position
? {
id: rel.position.id.toString(),
indexVal: rel.position.indexVal,
}
: null,
originGood: rel.originGood
? {
id: rel.originGood.id.toString(),
sdsGoodId: rel.originGood.sdsGoodId,
goodName: rel.originGood.goodName,
goodImage: rel.originGood.goodImage,
goodPrice:
rel.originGood.goodPrice === null ||
rel.originGood.goodPrice === undefined
? null
: (rel.originGood.goodPrice as { toString(): string }).toString(),
}
: null,
};
}
}
export interface PaginatedGoods {
items: GoodDto[];
total: number;
page: number;
pageSize: number;
}