feat(product-edit):商品编辑页初版
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/**
|
||||
* M3.0 editor entry and read-model contracts. Draft mutation, pricing, and
|
||||
* publishing DTOs intentionally stay out of this first editor slice.
|
||||
*/
|
||||
export type ProductEditorContext = {
|
||||
collection_item_id: string;
|
||||
product_id: string;
|
||||
profile_id: string;
|
||||
target_store: { id: string; name: string; currency_code: string };
|
||||
editor_path: string;
|
||||
};
|
||||
|
||||
export type ProductEditorSnapshot = {
|
||||
product: {
|
||||
id: string;
|
||||
revision: number;
|
||||
common: {
|
||||
source_title: string | null;
|
||||
brand: string | null;
|
||||
model: string | null;
|
||||
barcode: string | null;
|
||||
purchase_url: string | null;
|
||||
supply_note: string | null;
|
||||
};
|
||||
};
|
||||
profile: {
|
||||
id: string;
|
||||
revision: number;
|
||||
platform_id: string;
|
||||
market_code: string | null;
|
||||
fulfillment: string;
|
||||
target_store: { id: string; name: string; currency_code: string };
|
||||
title: string | null;
|
||||
description: string | null;
|
||||
tags: string[];
|
||||
category: {
|
||||
id: string | null;
|
||||
platform_type_id: string | null;
|
||||
source: string | null;
|
||||
};
|
||||
};
|
||||
variants: Array<{
|
||||
id: string;
|
||||
source_variant_key: string | null;
|
||||
source_sku: string | null;
|
||||
display_name: string | null;
|
||||
sort_order: number;
|
||||
purchase_cost_cny: string | null;
|
||||
listing: {
|
||||
id: string;
|
||||
offer_id: string | null;
|
||||
status: string;
|
||||
selling_price: string | null;
|
||||
list_price: string | null;
|
||||
currency_code: string | null;
|
||||
};
|
||||
}>;
|
||||
attributes: Array<{
|
||||
id: string;
|
||||
scope: 'common' | 'variant';
|
||||
variant_id: string | null;
|
||||
platform_attribute_id: string;
|
||||
complex_id: string;
|
||||
values: unknown;
|
||||
language_code: string | null;
|
||||
source: string;
|
||||
confirmation_status: string;
|
||||
}>;
|
||||
unmapped_attributes: Array<{
|
||||
id: string;
|
||||
variant_id: string | null;
|
||||
original_platform_category_id: string | null;
|
||||
original_platform_attribute_id: string;
|
||||
original_complex_id: string;
|
||||
original_name: string;
|
||||
values: unknown;
|
||||
language_code: string | null;
|
||||
reason: string;
|
||||
status: string;
|
||||
}>;
|
||||
warnings: Array<{ code: string; message: string }>;
|
||||
};
|
||||
|
||||
const uuid = z.uuid();
|
||||
const nullableText = (max: number) => z.string().trim().max(max).nullable();
|
||||
|
||||
/** M3.1 intentionally covers editable product/profile/SKU fundamentals. */
|
||||
export const saveProductEditorDraftRequestSchema = z.object({
|
||||
common: z.object({
|
||||
source_title: nullableText(1_000),
|
||||
brand: nullableText(300),
|
||||
model: nullableText(300),
|
||||
barcode: nullableText(300),
|
||||
purchase_url: z.url().nullable(),
|
||||
supply_note: nullableText(4_000),
|
||||
}).strict(),
|
||||
profile: z.object({
|
||||
target_store_id: uuid,
|
||||
fulfillment: z.enum(['rfbs', 'fbs', 'fbo', 'fbp', 'unknown']),
|
||||
title: nullableText(1_000),
|
||||
description: nullableText(100_000),
|
||||
tags: z.array(z.string().trim().min(1).max(100)).max(30),
|
||||
}).strict(),
|
||||
variants: z.array(z.object({
|
||||
id: uuid.nullable(),
|
||||
client_key: z.string().trim().min(1).max(100).nullable(),
|
||||
copy_from_variant_id: uuid.nullable().optional(),
|
||||
display_name: nullableText(1_000),
|
||||
source_sku: nullableText(500),
|
||||
purchase_cost_cny: z.string().regex(/^\d+(\.\d{1,4})?$/).nullable(),
|
||||
offer_id: nullableText(500),
|
||||
}).strict().superRefine((variant, context) => {
|
||||
if (!variant.id && !variant.client_key) {
|
||||
context.addIssue({ code: 'custom', path: ['client_key'], message: '新 SKU 必须提供 client_key' });
|
||||
}
|
||||
})).min(1).max(100),
|
||||
}).strict();
|
||||
|
||||
export type SaveProductEditorDraftRequest = z.infer<typeof saveProductEditorDraftRequestSchema>;
|
||||
export type SaveProductEditorDraftResponse = {
|
||||
product_revision: number;
|
||||
profile_revision: number;
|
||||
created_variants: Array<{ client_key: string; id: string }>;
|
||||
warnings: Array<{ code: string; message: string }>;
|
||||
};
|
||||
Reference in New Issue
Block a user