feat(category): 类目树、类目属性、属性字典维护系统构建完成
This commit is contained in:
@@ -56,6 +56,8 @@ export type ProductEditorCategoryOption = {
|
||||
};
|
||||
|
||||
export type ProductAttributeSchema = {
|
||||
/** Atlas 平台属性定义 UUID,用于精确限定同一类型下的字典作用域。 */
|
||||
attribute_id: string;
|
||||
platform_attribute_id: string;
|
||||
complex_id: string;
|
||||
name: string;
|
||||
@@ -75,11 +77,46 @@ export type ProductAttributeSchema = {
|
||||
| null;
|
||||
};
|
||||
|
||||
export type ProductCatalogCacheStatus =
|
||||
'fresh' | 'stale' | 'expired' | 'missing';
|
||||
|
||||
export type ProductCatalogCacheMetadata = {
|
||||
status: ProductCatalogCacheStatus;
|
||||
last_success_at: string | null;
|
||||
fresh_until: string | null;
|
||||
expires_at: string | null;
|
||||
is_complete: boolean;
|
||||
refresh_run_id: string | null;
|
||||
refresh_status: string | null;
|
||||
retry_after_ms: number | null;
|
||||
};
|
||||
|
||||
export type ProductCatalogRefreshRun = {
|
||||
id: string;
|
||||
platform_id: string;
|
||||
scope: string;
|
||||
status: string;
|
||||
trigger_kind: string;
|
||||
priority: 'high' | 'low';
|
||||
created_at: string;
|
||||
};
|
||||
|
||||
export type ProductAttributeSchemaResult = {
|
||||
items: ProductAttributeSchema[];
|
||||
cache: ProductCatalogCacheMetadata;
|
||||
};
|
||||
|
||||
export type ProductAttributeDictionaryValue = {
|
||||
value_id: string;
|
||||
value: string;
|
||||
};
|
||||
|
||||
export type ProductAttributeDictionaryResult = {
|
||||
items: ProductAttributeDictionaryValue[];
|
||||
next_cursor: string | null;
|
||||
cache: ProductCatalogCacheMetadata;
|
||||
};
|
||||
|
||||
export type ProductEditorValidationIssue = {
|
||||
code: string;
|
||||
field: string;
|
||||
@@ -102,10 +139,22 @@ export type ProductEditorValidation = {
|
||||
}>;
|
||||
};
|
||||
|
||||
/**
|
||||
* M3.0 editor entry and read-model contracts. Draft mutation, pricing, and
|
||||
* publishing DTOs intentionally stay out of this first editor slice.
|
||||
*/
|
||||
export type ProductPublishPreflight = {
|
||||
status: 'ready' | 'blocked' | 'refreshing';
|
||||
validation: ProductEditorValidation;
|
||||
catalog: {
|
||||
schema: ProductCatalogCacheMetadata;
|
||||
dictionaries: Array<{
|
||||
attribute_id: string;
|
||||
platform_attribute_id: string;
|
||||
name: string;
|
||||
cache: ProductCatalogCacheMetadata;
|
||||
}>;
|
||||
};
|
||||
refresh_runs: ProductCatalogRefreshRun[];
|
||||
};
|
||||
|
||||
/** 商品编辑入口与完整读模型;真正的发布 job DTO 仍在后续纵向任务中定义。 */
|
||||
export type ProductEditorContext = {
|
||||
collection_item_id: string;
|
||||
product_id: string;
|
||||
@@ -369,6 +418,20 @@ export const productAiSourceMaterialOverridesSchema =
|
||||
.partial()
|
||||
.strict();
|
||||
|
||||
export const productPublishPreflightRequestSchema = z
|
||||
.object({
|
||||
variant_ids: z
|
||||
.array(uuid)
|
||||
.min(1)
|
||||
.max(100)
|
||||
.refine((ids) => new Set(ids).size === ids.length, 'SKU 不能重复'),
|
||||
})
|
||||
.strict();
|
||||
|
||||
export type ProductPublishPreflightRequest = z.infer<
|
||||
typeof productPublishPreflightRequestSchema
|
||||
>;
|
||||
|
||||
/** M3.1 intentionally covers editable product/profile/SKU fundamentals. */
|
||||
export const saveProductEditorDraftRequestSchema = z
|
||||
.object({
|
||||
@@ -399,6 +462,8 @@ export const saveProductEditorDraftRequestSchema = z
|
||||
title: nullableText(1_000),
|
||||
description: nullableText(100_000),
|
||||
tags: z.array(z.string().trim().min(1).max(100)).max(30),
|
||||
platform_product_category_id: uuid.nullable().optional(),
|
||||
/** 旧客户端过渡字段;服务端会按外部 ID 映射到平台类目。 */
|
||||
store_product_category_id: uuid.nullable().optional(),
|
||||
category_source: z
|
||||
.enum(['source_capture', 'ai_suggestion', 'manual'])
|
||||
|
||||
Reference in New Issue
Block a user