File size: 8,271 Bytes
551658a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
from pydantic import BaseModel, Field
from datetime import datetime
from typing import Optional, List

# 商品基础信息
class ProductBase(BaseModel):
    category_id: int = Field(default=0, description="分类 ID")
    product_number: str = Field(default="", description="产品货号,11 位 UUID", max_length=11)
    model: str = Field(default="", description="产品型号,业务输入", max_length=50)
    name: str = Field(default="", description="产品名称", max_length=200)
    brand: str = Field(default="", description="品牌名称", max_length=100)
    price: float = Field(default=0.0, description="价格")
    original_price: float = Field(default=0.0, description="原价")
    currency: str = Field(default="USD", description="货币符号", max_length=10)
    stock: int = Field(default=0, description="库存")
    min_order: int = Field(default=1, description="最小起订量")
    unit: str = Field(default="pcs", description="计量单位", max_length=20)
    status: int = Field(default=1, description="状态:0-下架,1-上架")
    is_new: int = Field(default=0, description="是否新品:0-否,1-是")
    is_hot: int = Field(default=0, description="是否热销:0-否,1-是")
    is_best_seller: int = Field(default=0, description="是否畅销:0-否,1-是")
    sort_order: int = Field(default=0, description="排序顺序")
    
    # 商品详情字段
    description: str = Field(default="", description="功能描述")
    usage: str = Field(default="", description="适用范围")
    material: str = Field(default="", description="材质", max_length=200)
    parameters: str = Field(default="", description="其他参数说明")
    
    # SEO 字段
    seo_title_tag: str = Field(default="", description="SEO 页面标题", max_length=200)
    seo_meta_keywords: str = Field(default="", description="SEO 元关键词", max_length=500)
    
    # 产地字段
    country_of_origin: str = Field(default="", description="原产国", max_length=100)
    made_in_label: str = Field(default="", description="Made in 标签", max_length=100)
    
    company_code: str = Field(default="", description="公司编码", max_length=50)

class ProductCreate(ProductBase):
    pass

class ProductUpdate(BaseModel):
    category_id: Optional[int] = None
    product_number: Optional[str] = None
    model: Optional[str] = None
    name: Optional[str] = None
    brand: Optional[str] = None
    price: Optional[float] = None
    original_price: Optional[float] = None
    currency: Optional[str] = None
    stock: Optional[int] = None
    min_order: Optional[int] = None
    unit: Optional[str] = None
    status: Optional[int] = None
    is_new: Optional[int] = None
    is_hot: Optional[int] = None
    is_best_seller: Optional[int] = None
    sort_order: Optional[int] = None
    description: Optional[str] = None
    usage: Optional[str] = None
    material: Optional[str] = None
    parameters: Optional[str] = None
    seo_title_tag: Optional[str] = None
    seo_meta_keywords: Optional[str] = None
    country_of_origin: Optional[str] = None
    made_in_label: Optional[str] = None

class ProductResponse(ProductBase):
    id: int
    created_at: datetime
    updated_at: Optional[datetime] = None
    
    class Config:
        from_attributes = True

# 商品媒体
class ProductMediaBase(BaseModel):
    product_number: str = Field(default="", description="产品货号", max_length=11)
    media_type: str = Field(default="image", description="媒体类型:image-图片,video-视频", max_length=20)
    r2_url: str = Field(default="", description="媒体 URL(R2 原图 URL)", max_length=500)
    thumbnail_r2_url: str = Field(default="", description="缩略图 URL(R2 缩略图 URL)", max_length=500)
    media_id: str = Field(default="", description="素材ID", max_length=32)
    media_alt: str = Field(default="", description="ALT 标签/描述", max_length=200)
    is_main: int = Field(default=0, description="是否主图:0-否,1-是")
    sort_order: int = Field(default=0, description="排序顺序")
    company_code: str = Field(default="", description="公司编码", max_length=50)

class ProductMediaCreate(ProductMediaBase):
    pass

class ProductMediaUpdate(BaseModel):
    media_type: Optional[str] = None
    r2_url: Optional[str] = None
    thumbnail_r2_url: Optional[str] = None
    media_id: Optional[str] = None
    media_alt: Optional[str] = None
    is_main: Optional[int] = None
    sort_order: Optional[int] = None

class ProductMediaResponse(ProductMediaBase):
    id: int
    created_at: datetime
    updated_at: datetime
    
    class Config:
        from_attributes = True

# 商品认证
class ProductCertificationBase(BaseModel):
    product_number: str = Field(default="", description="产品货号", max_length=11)
    certification_type: str = Field(default="", description="认证类型", max_length=50)
    r2_url: str = Field(default="", description="认证文件 URL(R2 URL)", max_length=500)
    thumbnail_r2_url: str = Field(default="", description="认证缩略图路径(R2 URL)", max_length=500)
    media_id: str = Field(default="", description="素材ID", max_length=32)
    company_code: str = Field(default="", description="公司编码", max_length=50)

class ProductCertificationCreate(ProductCertificationBase):
    pass

class ProductCertificationUpdate(BaseModel):
    certification_type: Optional[str] = None
    r2_url: Optional[str] = None
    thumbnail_r2_url: Optional[str] = None
    media_id: Optional[str] = None

class ProductCertificationResponse(ProductCertificationBase):
    id: int
    created_at: datetime
    updated_at: datetime
    
    class Config:
        from_attributes = True

# 商品包装
class ProductPackagingBase(BaseModel):
    product_number: str = Field(default="", description="产品货号", max_length=11)
    model: str = Field(default="", description="型号", max_length=50)
    length: float = Field(default=0.0, description="长度 (cm)")
    width: float = Field(default=0.0, description="宽度 (cm)")
    height: float = Field(default=0.0, description="高度 (cm)")
    volume: float = Field(default=0.0, description="体积 (cm³)")
    weight: float = Field(default=0.0, description="重量 (g)")
    company_code: str = Field(default="", description="公司编码", max_length=50)

class ProductPackagingCreate(ProductPackagingBase):
    pass

class ProductPackagingUpdate(BaseModel):
    model: Optional[str] = None
    length: Optional[float] = None
    width: Optional[float] = None
    height: Optional[float] = None
    volume: Optional[float] = None
    weight: Optional[float] = None

class ProductPackagingResponse(ProductPackagingBase):
    id: int
    created_at: datetime
    updated_at: datetime
    
    class Config:
        from_attributes = True

# 商品详情(包含所有关联数据)
class ProductDetailResponse(ProductResponse):
    media: List[ProductMediaResponse] = []
    certifications: List[ProductCertificationResponse] = []
    packaging: List[ProductPackagingResponse] = []
    
    class Config:
        from_attributes = True

# 公司 R2 配置
class CompanyR2ConfigBase(BaseModel):
    company_code: str = Field(..., description="公司编码")
    r2_account_id: str = Field(..., description="R2 账户 ID")
    r2_access_key_id: str = Field(..., description="R2 访问密钥 ID")
    r2_secret_access_key: str = Field(..., description="R2 密钥")
    r2_bucket_name: str = Field(..., description="R2 桶名称")
    r2_public_url: str = Field(..., description="R2 公共访问 URL")
    r2_enabled: int = Field(..., description="是否启用 R2:0-禁用,1-启用")

class CompanyR2ConfigCreate(CompanyR2ConfigBase):
    pass

class CompanyR2ConfigUpdate(BaseModel):
    r2_account_id: Optional[str] = None
    r2_access_key_id: Optional[str] = None
    r2_secret_access_key: Optional[str] = None
    r2_bucket_name: Optional[str] = None
    r2_public_url: Optional[str] = None
    r2_enabled: Optional[int] = None

class CompanyR2ConfigResponse(CompanyR2ConfigBase):
    id: int
    created_at: datetime
    updated_at: Optional[datetime] = None
    company_name: Optional[str] = None
    
    class Config:
        from_attributes = True