feat(admin): product families api client and types

This commit is contained in:
yeuimu
2026-08-28 13:25:10 +08:00
parent 8fad8de73e
commit c492469d70
3 changed files with 298 additions and 0 deletions
+64
View File
@@ -0,0 +1,64 @@
import request from './request'
import type {
AutoGroupPreviewGroup,
FamilyPriceOverrideRow,
PaginatedResult,
ProductFamily,
} from '@/types'
export const productFamiliesApi = {
list: (params: { keyword?: string; page?: number; pageSize?: number }) => {
return request.get<any, PaginatedResult<ProductFamily>>('/product-families', { params })
},
detail: (id: string) => {
return request.get<any, ProductFamily>(`/product-families/${id}`)
},
create: (data: {
familyName: string
familyCode?: string
familyImage?: string
originGoodIds?: string[]
primaryOriginGoodId?: string
}) => {
return request.post<any, ProductFamily>('/product-families', data)
},
patch: (id: string, data: Record<string, unknown>) => {
return request.patch<any, ProductFamily>(`/product-families/${id}`, data)
},
autoGroup: (apply: boolean) => {
return request.post<any, { applied: number; groups: AutoGroupPreviewGroup[] }>(
'/product-families/auto-group',
{ apply },
)
},
updateMembers: (id: string, data: { addOriginGoodIds?: string[]; removeOriginGoodIds?: string[] }) => {
return request.post<any, ProductFamily>(`/product-families/${id}/members`, data)
},
createCustomMember: (id: string, data: Record<string, unknown>) => {
return request.post<any, unknown>(`/product-families/${id}/members/custom`, data)
},
recompute: (id: string) => {
return request.post<any, ProductFamily>(`/product-families/${id}/recompute`)
},
listOverrides: (id: string) => {
return request.get<any, { items: FamilyPriceOverrideRow[] }>(`/product-families/${id}/price-overrides`)
},
putOverrides: (id: string, items: Array<Record<string, unknown>>) => {
return request.put<any, { items: FamilyPriceOverrideRow[] }>(`/product-families/${id}/price-overrides`, { items })
},
deleteOverrides: (id: string, cells: Array<Record<string, unknown>>) => {
return request.delete<any, { items: FamilyPriceOverrideRow[] }>(`/product-families/${id}/price-overrides`, {
data: { cells },
})
},
}
+87
View File
@@ -378,6 +378,10 @@ export interface OriginGoodsTreeNode {
variantCount: number
sizeRowCount: number
packageRowCount: number
familyId: string | null
familyName: string | null
familyCode: string | null
familyStale: boolean | null
}
export interface OriginGoodsTreeCategoryNode {
@@ -396,6 +400,89 @@ export interface OriginGoodsTreeResponse {
configuredCount: number
}
// Product Family (SPU layer) types
export interface ProductFamilyMember {
id: string
sdsGoodId: string
goodName: string
goodImage: string | null
source: 'SDS' | 'CUSTOM'
delisted: boolean
skuCode: string | null
logisticsLabel: string | null
craftLabel: string | null
warehouseLabel: string | null
}
export interface FamilyPriceOverrideRow {
id: string
familyId: string
sizeId: string
colorId: string
craft: string
logistics: string
price: string
note: string | null
derivedPrice: string | null
diff: string | null
}
export interface ProductFamilyPriceMatrix {
sizes: Array<{ key: string; name: string | null }>
colors: Array<{ key: string; name: string | null; hex: string | null; imageUrl: string | null }>
crafts: string[]
logistics: string[]
rows: Array<{
sizeId: string
sizeName: string | null
colorId: string
colorName: string | null
craft: string
logistics: string
price: string
manual: boolean
sources: Array<{ sdsGoodId: string; sdsVariantId: string; price: string }>
}>
}
export interface ProductFamily {
id: string
familyCode: string | null
familyName: string
familyImage: string | null
countryId: string | null
categoryId: string | null
primaryOriginGoodId: string | null
autoManaged: boolean
stale: boolean
detail: Record<string, unknown> | null
sizeChart: { columns?: unknown; rows?: Array<Record<string, unknown>> } | null
packageSpecs: { columns?: unknown; rows?: Array<Record<string, unknown>> } | null
priceMatrix: ProductFamilyPriceMatrix | null
originGoods: ProductFamilyMember[]
priceOverrides: FamilyPriceOverrideRow[]
_count: { originGoods: number; priceOverrides: number }
}
export interface AutoGroupPreviewGroup {
groupKey: string
familyName: string
familyCode: string | null
memberCount: number
sampleNames: string[]
}
export interface CustomMemberVariantInput {
sku: string
sizeId?: string | null
sizeName?: string | null
colorId?: string | null
colorName?: string | null
colorHex?: string | null
imageUrl?: string | null
price: number
}
// Sync types
export interface SyncLog {
id: string