916bdd9c7c
- 新增 category.archive_kind 与 kind_field 字段模板表(迁移 0010) - 种子 electronics 字段模板 + 3C 品类树(手机/笔记本/平板等) - 后端按档案模式动态计算完整度/合格:食品沿用 food_detail, 其它模式走 product.attributes + kind_field - 新增 GET /api/kind-fields?kind= 接口 - 后台编辑页按品类模式动态渲染规格参数表单 - 公开详情页/接口输出带标签的规格表 Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
219 lines
4.5 KiB
TypeScript
219 lines
4.5 KiB
TypeScript
export interface ProductRow {
|
|
id: string;
|
|
gtin: string | null;
|
|
name: string;
|
|
brand: string | null;
|
|
category_path: string | null;
|
|
status: string;
|
|
quality_score: number;
|
|
missing: string[];
|
|
updated_at: string;
|
|
}
|
|
|
|
export interface Barcode {
|
|
id: string;
|
|
gtin: string;
|
|
gtin_type: string;
|
|
pack_level: string;
|
|
region: string | null;
|
|
is_primary: boolean;
|
|
}
|
|
|
|
export interface ProductImage {
|
|
id: string;
|
|
url: string;
|
|
kind: string;
|
|
license: string | null;
|
|
}
|
|
|
|
export interface MSRP {
|
|
id: string;
|
|
amount: number;
|
|
currency: string;
|
|
region: string;
|
|
effective_date: string | null;
|
|
source_url: string | null;
|
|
note: string | null;
|
|
}
|
|
|
|
export interface ProductDetail {
|
|
id: string;
|
|
gtin: string | null;
|
|
name: string;
|
|
brand_id: string | null;
|
|
brand: string | null;
|
|
category_id: string | null;
|
|
category_path: string | null;
|
|
archive_kind: string;
|
|
attributes: Record<string, unknown>;
|
|
net_content_value: number | null;
|
|
net_content_unit: string | null;
|
|
country_of_origin: string | null;
|
|
status: string;
|
|
quality_score: number;
|
|
ingredients_text: string | null;
|
|
allergens: string[];
|
|
additives: string[];
|
|
nutriments: Record<string, number> | null;
|
|
nutrition_basis: string | null;
|
|
serving_size: string | null;
|
|
nutri_score: string | null;
|
|
barcodes: Barcode[];
|
|
images: ProductImage[];
|
|
msrp: MSRP[];
|
|
missing: string[];
|
|
updated_at: string;
|
|
}
|
|
|
|
export interface Brand {
|
|
id: string;
|
|
name: string;
|
|
product_count: number;
|
|
}
|
|
|
|
export interface Category {
|
|
id: string;
|
|
name_zh: string;
|
|
name_en: string | null;
|
|
path: string;
|
|
level: number;
|
|
parent_id: string | null;
|
|
gpc_brick_code: string | null;
|
|
archive_kind: string;
|
|
product_count: number;
|
|
}
|
|
|
|
export interface KindField {
|
|
kind: string;
|
|
field_key: string;
|
|
group_label: string;
|
|
label_zh: string;
|
|
field_type: string;
|
|
unit: string | null;
|
|
options: string[];
|
|
placeholder: string | null;
|
|
sort_order: number;
|
|
qualified: boolean;
|
|
}
|
|
|
|
export interface CategoryInput {
|
|
name_zh: string;
|
|
name_en?: string | null;
|
|
slug?: string | null;
|
|
parent_id?: string | null;
|
|
gpc_brick_code?: string | null;
|
|
}
|
|
|
|
export interface AuditEntry {
|
|
id: string;
|
|
actor: string;
|
|
action: string;
|
|
fields: string[];
|
|
created_at: string;
|
|
}
|
|
|
|
export interface AuditLogRow {
|
|
id: string;
|
|
actor: string;
|
|
action: string;
|
|
entity: string;
|
|
entity_id: string | null;
|
|
fields: string[];
|
|
created_at: string;
|
|
}
|
|
|
|
export interface AdminStats {
|
|
products: number;
|
|
qualified: number;
|
|
min_score: number;
|
|
by_status: Record<string, number>;
|
|
brands: number;
|
|
categories: number;
|
|
pending_submissions: number;
|
|
avg_quality: number;
|
|
}
|
|
|
|
export interface SubmissionRow {
|
|
id: string;
|
|
gtin: string | null;
|
|
name: string;
|
|
status: string;
|
|
submitter_name: string | null;
|
|
matched: boolean;
|
|
created_at: string;
|
|
reviewed_at: string | null;
|
|
}
|
|
|
|
export interface SubmissionImage {
|
|
url: string;
|
|
kind: string;
|
|
}
|
|
|
|
export interface SubmissionPayload {
|
|
gtin: string | null;
|
|
name: string;
|
|
brand_name: string | null;
|
|
category_id: string | null;
|
|
net_content_value: number | null;
|
|
net_content_unit: string | null;
|
|
country_of_origin: string | null;
|
|
ingredients_text: string | null;
|
|
nutriments: Record<string, number> | null;
|
|
nutrition_basis: string | null;
|
|
serving_size: string | null;
|
|
nutri_score: string | null;
|
|
images: SubmissionImage[] | null;
|
|
submitter_name: string | null;
|
|
submitter_contact: string | null;
|
|
note: string | null;
|
|
}
|
|
|
|
export interface SubmissionDetail {
|
|
id: string;
|
|
status: string;
|
|
gtin: string | null;
|
|
name: string;
|
|
submitter_name: string | null;
|
|
submitter_contact: string | null;
|
|
note: string | null;
|
|
review_note: string | null;
|
|
reviewed_by: string | null;
|
|
reviewed_at: string | null;
|
|
created_at: string;
|
|
target_product_id: string | null;
|
|
result_product_id: string | null;
|
|
payload: SubmissionPayload;
|
|
existing_product?: ProductDetail;
|
|
}
|
|
|
|
export interface ApiKeyUsage {
|
|
total: number;
|
|
today: number;
|
|
last_used_at?: number | null;
|
|
}
|
|
|
|
export interface ApiKey {
|
|
id: string;
|
|
name: string;
|
|
key_prefix: string;
|
|
owner_email: string | null;
|
|
tier: string;
|
|
rate_limit_per_min: number;
|
|
revoked_at: string | null;
|
|
created_by: string | null;
|
|
created_at: string;
|
|
usage: ApiKeyUsage;
|
|
}
|
|
|
|
export const FIELD_LABELS: Record<string, string> = {
|
|
name: "名称",
|
|
gtin: "条码",
|
|
brand: "品牌",
|
|
category: "品类",
|
|
net_content: "净含量",
|
|
country_of_origin: "产地",
|
|
nutriments: "营养成分",
|
|
ingredients: "配料",
|
|
image: "图片",
|
|
};
|