@@ -367,310 +367,310 @@ const platformSpecOptions: Array<{
} > = [
{
label : "淘宝/天猫" ,
ratios : [ "淘宝主图 / SKU 鍥? 800脳 800px" , "详情页宽 750px" , "详情页宽 790px" ] ,
defaultRatio : "淘宝主图 / SKU 鍥? 800脳 800px" ,
ratios : [ "淘宝主图 / SKU 图 800× 800px" , "详情页宽 750px" , "详情页宽 790px" ] ,
defaultRatio : "淘宝主图 / SKU 图 800× 800px" ,
ratioGroups : {
set : {
ratios : [ "1000脳 1000px\u00a0\u00a0\u00a01锛? " , "800脳 800px\u00a0\u00a0\u00a01锛? " ] ,
defaultRatio : "1000脳 1000px\u00a0\u00a0\u00a01锛? " ,
ratios : [ "1000× 1000px\u00a0\u00a0\u00a01:1 " , "800× 800px\u00a0\u00a0\u00a01:1 " ] ,
defaultRatio : "1000× 1000px\u00a0\u00a0\u00a01:1 " ,
} ,
detail : {
ratios : [
"750脳 1000px\u00a0\u00a0\u00a03锛? " ,
"790脳 1053px\u00a0\u00a0\u00a03锛? " ,
"750脳 1125px\u00a0\u00a0\u00a02锛? " ,
"790脳 1185px\u00a0\u00a0\u00a02锛? " ,
"750× 1000px\u00a0\u00a0\u00a03:4 " ,
"790× 1053px\u00a0\u00a0\u00a03:4 " ,
"750× 1125px\u00a0\u00a0\u00a02:3 " ,
"790× 1185px\u00a0\u00a0\u00a02:3 " ,
] ,
defaultRatio : "750脳 1000px\u00a0\u00a0\u00a03锛? " ,
defaultRatio : "750× 1000px\u00a0\u00a0\u00a03:4 " ,
} ,
model : {
ratios : [ "750脳 1000px\u00a0\u00a0\u00a03锛? " ] ,
defaultRatio : "750脳 1000px\u00a0\u00a0\u00a03锛? " ,
ratios : [ "750× 1000px\u00a0\u00a0\u00a03:4 " ] ,
defaultRatio : "750× 1000px\u00a0\u00a0\u00a03:4 " ,
} ,
video : {
ratios : [ "1080脳 1920px\u00a0\u00a0\u00a09锛? 6" , "1080脳 1440px\u00a0\u00a0\u00a03锛? " , "1080脳 1080px\u00a0\u00a0\u00a01锛? " ] ,
defaultRatio : "1080脳 1920px\u00a0\u00a0\u00a09锛? 6" ,
ratios : [ "1080× 1920px\u00a0\u00a0\u00a09:1 6" , "1080× 1440px\u00a0\u00a0\u00a03:4 " , "1080× 1080px\u00a0\u00a0\u00a01:1 " ] ,
defaultRatio : "1080× 1920px\u00a0\u00a0\u00a09:1 6" ,
} ,
hot : {
ratios : [ "800脳 800px\u00a0\u00a0\u00a01锛? " ] ,
defaultRatio : "800脳 800px\u00a0\u00a0\u00a01锛? " ,
ratios : [ "800× 800px\u00a0\u00a0\u00a01:1 " ] ,
defaultRatio : "800× 800px\u00a0\u00a0\u00a01:1 " ,
} ,
} ,
specs : [ "主图 / SKU 鍥? 800脳 800px锛屸墹 3MB" , "详情页宽 750px 或? 790px锛屽崟寮犻珮鈮? 546px" ] ,
tip : "建议主图 200-400KB JPG锛岃秴杩? 500KB 浼氬奖鍝嶅姞杞介€熷害銆? " ,
specs : [ "主图 / SKU 图 800× 800px,≤ 3MB" , "详情页宽 750px 或 790px,单张高度≤1 546px" ] ,
tip : "建议主图 200-400KB JPG,超过 500KB 会影响加载速度。 " ,
} ,
{
label : "京东" ,
ratios : [ "京东主图 / SKU 鍥? 800脳 800px" , "详情页宽 750px" , "首图主体占比 鈮? 0%" ] ,
defaultRatio : "京东主图 / SKU 鍥? 800脳 800px" ,
ratios : [ "京东主图 / SKU 图 800× 800px" , "详情页宽 750px" , "首图主体占比 ≥8 0%" ] ,
defaultRatio : "京东主图 / SKU 图 800× 800px" ,
ratioGroups : {
set : {
ratios : [ "1000脳 1000px\u00a0\u00a0\u00a01锛? " ] ,
defaultRatio : "1000脳 1000px\u00a0\u00a0\u00a01锛? " ,
ratios : [ "1000× 1000px\u00a0\u00a0\u00a01:1 " ] ,
defaultRatio : "1000× 1000px\u00a0\u00a0\u00a01:1 " ,
} ,
detail : {
ratios : [
"750脳 1000px\u00a0\u00a0\u00a03锛? " ,
"990脳 1320px\u00a0\u00a0\u00a03锛? " ,
"750脳 1125px\u00a0\u00a0\u00a02锛? " ,
"990脳 1485px\u00a0\u00a0\u00a02锛? " ,
"750× 1000px\u00a0\u00a0\u00a03:4 " ,
"990× 1320px\u00a0\u00a0\u00a03:4 " ,
"750× 1125px\u00a0\u00a0\u00a02:3 " ,
"990× 1485px\u00a0\u00a0\u00a02:3 " ,
] ,
defaultRatio : "750脳 1000px\u00a0\u00a0\u00a03锛? " ,
defaultRatio : "750× 1000px\u00a0\u00a0\u00a03:4 " ,
} ,
model : {
ratios : [ "750脳 1125px\u00a0\u00a0\u00a02锛? " , "990脳 1485px\u00a0\u00a0\u00a02锛? " ] ,
defaultRatio : "750脳 1125px\u00a0\u00a0\u00a02锛? " ,
ratios : [ "750× 1125px\u00a0\u00a0\u00a02:3 " , "990× 1485px\u00a0\u00a0\u00a02:3 " ] ,
defaultRatio : "750× 1125px\u00a0\u00a0\u00a02:3 " ,
} ,
video : {
ratios : [ "1080脳 1920px\u00a0\u00a0\u00a09锛? 6" , "1920脳 1080px\u00a0\u00a0\u00a016锛? " ] ,
defaultRatio : "1080脳 1920px\u00a0\u00a0\u00a09锛? 6" ,
ratios : [ "1080× 1920px\u00a0\u00a0\u00a09:1 6" , "1920× 1080px\u00a0\u00a0\u00a016:9 " ] ,
defaultRatio : "1080× 1920px\u00a0\u00a0\u00a09:1 6" ,
} ,
hot : {
ratios : [ "800脳 800px\u00a0\u00a0\u00a01锛? " ] ,
defaultRatio : "800脳 800px\u00a0\u00a0\u00a01锛? " ,
ratios : [ "800× 800px\u00a0\u00a0\u00a01:1 " ] ,
defaultRatio : "800× 800px\u00a0\u00a0\u00a01:1 " ,
} ,
} ,
specs : [ "主图 / SKU 鍥? 800脳 800px锛岀櫧搴曪紝鈮? MB" , "详情页宽 750px锛岄鍥句富浣撳崰姣?鈮? 0%" ] ,
specs : [ "主图 / SKU 图 800× 800px,白底,≤3 MB" , "详情页宽 750px,首图主体占比 ≥8 0%" ] ,
} ,
{
label : "拼多多" ,
ratios : [ "主图 750脳 352px" , "主图 800脳 800px" , "详情页宽 750px" ] ,
defaultRatio : "主图 750脳 352px" ,
ratios : [ "主图 750× 352px" , "主图 800× 800px" , "详情页宽 750px" ] ,
defaultRatio : "主图 750× 352px" ,
ratioGroups : {
set : {
ratios : [ "800脳 800px\u00a0\u00a0\u00a01锛? " , "750脳 1000px\u00a0\u00a0\u00a03锛? " ] ,
defaultRatio : "800脳 800px\u00a0\u00a0\u00a01锛? " ,
ratios : [ "800× 800px\u00a0\u00a0\u00a01:1 " , "750× 1000px\u00a0\u00a0\u00a03:4 " ] ,
defaultRatio : "800× 800px\u00a0\u00a0\u00a01:1 " ,
} ,
detail : {
ratios : [ "750脳 1000px\u00a0\u00a0\u00a03锛? " , "750脳 1125px\u00a0\u00a0\u00a02锛? " ] ,
defaultRatio : "750脳 1000px\u00a0\u00a0\u00a03锛? " ,
ratios : [ "750× 1000px\u00a0\u00a0\u00a03:4 " , "750× 1125px\u00a0\u00a0\u00a02:3 " ] ,
defaultRatio : "750× 1000px\u00a0\u00a0\u00a03:4 " ,
} ,
model : {
ratios : [ "750脳 1000px\u00a0\u00a0\u00a03锛? " ] ,
defaultRatio : "750脳 1000px\u00a0\u00a0\u00a03锛? " ,
ratios : [ "750× 1000px\u00a0\u00a0\u00a03:4 " ] ,
defaultRatio : "750× 1000px\u00a0\u00a0\u00a03:4 " ,
} ,
video : {
ratios : [ "1080脳 1920px\u00a0\u00a0\u00a09锛? 6" ] ,
defaultRatio : "1080脳 1920px\u00a0\u00a0\u00a09锛? 6" ,
ratios : [ "1080× 1920px\u00a0\u00a0\u00a09:1 6" ] ,
defaultRatio : "1080× 1920px\u00a0\u00a0\u00a09:1 6" ,
} ,
hot : {
ratios : [ "800脳 800px\u00a0\u00a0\u00a01锛? " ] ,
defaultRatio : "800脳 800px\u00a0\u00a0\u00a01锛? " ,
ratios : [ "800× 800px\u00a0\u00a0\u00a01:1 " ] ,
defaultRatio : "800× 800px\u00a0\u00a0\u00a01:1 " ,
} ,
} ,
specs : [ "主图 750脳 352px 或? 800脳 800px锛屸墹 1MB" , "详情页宽 750px,要求纯白底、无水印、无拼接" ] ,
specs : [ "主图 750× 352px 或 800× 800px,≤ 1MB" , "详情页宽 750px,要求纯白底、无水印、无拼接" ] ,
} ,
{
label : "抖音电商" ,
ratios : [ "鐭棰? 1080脳 1920px" ] ,
defaultRatio : "鐭棰? 1080脳 1920px" ,
ratios : [ "短视频 1080× 1920px" ] ,
defaultRatio : "短视频 1080× 1920px" ,
ratioGroups : {
video : {
ratios : [ "1080脳 1920px\u00a0\u00a0\u00a09锛? 6" ] ,
defaultRatio : "1080脳 1920px\u00a0\u00a0\u00a09锛? 6" ,
ratios : [ "1080× 1920px\u00a0\u00a0\u00a09:1 6" ] ,
defaultRatio : "1080× 1920px\u00a0\u00a0\u00a09:1 6" ,
} ,
hot : {
ratios : [ "800脳 800px\u00a0\u00a0\u00a01锛? " ] ,
defaultRatio : "800脳 800px\u00a0\u00a0\u00a01锛? " ,
ratios : [ "800× 800px\u00a0\u00a0\u00a01:1 " ] ,
defaultRatio : "800× 800px\u00a0\u00a0\u00a01:1 " ,
} ,
} ,
specs : [ "鐭棰? 1080脳 1920px锛? :16" , "30s 图呮渶浣? " ] ,
specs : [ "短视频 1080× 1920px, 9 :16" , "30s 内最佳 " ] ,
} ,
{
label : "亚马逊 Amazon" ,
ratios : [ "主图 鈮? 600脳 1600px" , "建议 2000脳 2000px+" , "鏈€灏? 500脳 500px" ] ,
defaultRatio : "主图 鈮? 600脳 1600px" ,
ratios : [ "主图 ≥1 600× 1600px" , "建议 2000× 2000px+" , "最小 500× 500px" ] ,
defaultRatio : "主图 ≥1 600× 1600px" ,
ratioGroups : {
set : {
ratios : [ "1600脳 1600px\u00a0\u00a0\u00a01锛? " ] ,
defaultRatio : "1600脳 1600px\u00a0\u00a0\u00a01锛? " ,
ratios : [ "1600× 1600px\u00a0\u00a0\u00a01:1 " ] ,
defaultRatio : "1600× 1600px\u00a0\u00a0\u00a01:1 " ,
} ,
detail : {
ratios : [ "1600脳 1600px\u00a0\u00a0\u00a01锛? " , "1200脳 1800px\u00a0\u00a0\u00a02锛? " , "1200脳 1600px\u00a0\u00a0\u00a03锛? " ] ,
defaultRatio : "1200脳 1800px\u00a0\u00a0\u00a02锛? " ,
ratios : [ "1600× 1600px\u00a0\u00a0\u00a01:1 " , "1200× 1800px\u00a0\u00a0\u00a02:3 " , "1200× 1600px\u00a0\u00a0\u00a03:4 " ] ,
defaultRatio : "1200× 1800px\u00a0\u00a0\u00a02:3 " ,
} ,
model : {
ratios : [ "1200脳 1800px\u00a0\u00a0\u00a02锛? " ] ,
defaultRatio : "1200脳 1800px\u00a0\u00a0\u00a02锛? " ,
ratios : [ "1200× 1800px\u00a0\u00a0\u00a02:3 " ] ,
defaultRatio : "1200× 1800px\u00a0\u00a0\u00a02:3 " ,
} ,
video : {
ratios : [ "1920脳 1080px\u00a0\u00a0\u00a016锛? " ] ,
defaultRatio : "1920脳 1080px\u00a0\u00a0\u00a016锛? " ,
ratios : [ "1920× 1080px\u00a0\u00a0\u00a016:9 " ] ,
defaultRatio : "1920× 1080px\u00a0\u00a0\u00a016:9 " ,
} ,
hot : {
ratios : [ "1600脳 1600px\u00a0\u00a0\u00a01锛? " ] ,
defaultRatio : "1600脳 1600px\u00a0\u00a0\u00a01锛? " ,
ratios : [ "1600× 1600px\u00a0\u00a0\u00a01:1 " ] ,
defaultRatio : "1600× 1600px\u00a0\u00a0\u00a01:1 " ,
} ,
} ,
specs : [ "主图 1600脳 1600px+,纯白底,≤10MB" , "鏈€灏? 500脳 500px锛屽缓璁? 2000px+ 浠ユ敮鎸佺缉鏀? " ] ,
aliases : [ "浜氶┈閫? " ] ,
specs : [ "主图 1600× 1600px+,纯白底,≤10MB" , "最小 500× 500px,建议 2000px+ 以支持缩放 " ] ,
aliases : [ "亚马逊 " ] ,
} ,
{
label : "Shopee" ,
ratios : [ "商品主图 1024脳 1024px" , "基础主图 800脳 800px" ] ,
defaultRatio : "商品主图 1024脳 1024px" ,
ratios : [ "商品主图 1024× 1024px" , "基础主图 800× 800px" ] ,
defaultRatio : "商品主图 1024× 1024px" ,
ratioGroups : {
set : {
ratios : [ "800脳 800px\u00a0\u00a0\u00a01锛? " ] ,
defaultRatio : "800脳 800px\u00a0\u00a0\u00a01锛? " ,
ratios : [ "800× 800px\u00a0\u00a0\u00a01:1 " ] ,
defaultRatio : "800× 800px\u00a0\u00a0\u00a01:1 " ,
} ,
detail : {
ratios : [ "750脳 1000px\u00a0\u00a0\u00a03锛? " , "750脳 1125px\u00a0\u00a0\u00a02锛? " ] ,
defaultRatio : "750脳 1000px\u00a0\u00a0\u00a03锛? " ,
ratios : [ "750× 1000px\u00a0\u00a0\u00a03:4 " , "750× 1125px\u00a0\u00a0\u00a02:3 " ] ,
defaultRatio : "750× 1000px\u00a0\u00a0\u00a03:4 " ,
} ,
model : {
ratios : [ "750脳 1000px\u00a0\u00a0\u00a03锛? " ] ,
defaultRatio : "750脳 1000px\u00a0\u00a0\u00a03锛? " ,
ratios : [ "750× 1000px\u00a0\u00a0\u00a03:4 " ] ,
defaultRatio : "750× 1000px\u00a0\u00a0\u00a03:4 " ,
} ,
video : {
ratios : [ "1080脳 1920px\u00a0\u00a0\u00a09锛? 6" ] ,
defaultRatio : "1080脳 1920px\u00a0\u00a0\u00a09锛? 6" ,
ratios : [ "1080× 1920px\u00a0\u00a0\u00a09:1 6" ] ,
defaultRatio : "1080× 1920px\u00a0\u00a0\u00a09:1 6" ,
} ,
hot : {
ratios : [ "800脳 800px\u00a0\u00a0\u00a01锛? " ] ,
defaultRatio : "800脳 800px\u00a0\u00a0\u00a01锛? " ,
ratios : [ "800× 800px\u00a0\u00a0\u00a01:1 " ] ,
defaultRatio : "800× 800px\u00a0\u00a0\u00a01:1 " ,
} ,
} ,
specs : [ "商品主图推荐 1024脳 1024px,基础 800脳 800px" , "鈮?MB锛岀櫧搴曟垨娴呰壊搴? " ] ,
specs : [ "商品主图推荐 1024× 1024px,基础 800× 800px" , "≤2MB,白底或浅色底 " ] ,
aliases : [ "虾皮 Shopee/Lazada" , "虾皮" ] ,
} ,
{
label : "Lazada" ,
ratios : [ "商品主图 800脳 800px" ] ,
defaultRatio : "商品主图 800脳 800px" ,
ratios : [ "商品主图 800× 800px" ] ,
defaultRatio : "商品主图 800× 800px" ,
ratioGroups : {
set : {
ratios : [ "800脳 800px\u00a0\u00a0\u00a01锛? " ] ,
defaultRatio : "800脳 800px\u00a0\u00a0\u00a01锛? " ,
ratios : [ "800× 800px\u00a0\u00a0\u00a01:1 " ] ,
defaultRatio : "800× 800px\u00a0\u00a0\u00a01:1 " ,
} ,
detail : {
ratios : [ "750脳 1000px\u00a0\u00a0\u00a03锛? " , "750脳 1125px\u00a0\u00a0\u00a02锛? " ] ,
defaultRatio : "750脳 1000px\u00a0\u00a0\u00a03锛? " ,
ratios : [ "750× 1000px\u00a0\u00a0\u00a03:4 " , "750× 1125px\u00a0\u00a0\u00a02:3 " ] ,
defaultRatio : "750× 1000px\u00a0\u00a0\u00a03:4 " ,
} ,
model : {
ratios : [ "750脳 1000px\u00a0\u00a0\u00a03锛? " ] ,
defaultRatio : "750脳 1000px\u00a0\u00a0\u00a03锛? " ,
ratios : [ "750× 1000px\u00a0\u00a0\u00a03:4 " ] ,
defaultRatio : "750× 1000px\u00a0\u00a0\u00a03:4 " ,
} ,
video : {
ratios : [ "1080脳 1920px\u00a0\u00a0\u00a09锛? 6" ] ,
defaultRatio : "1080脳 1920px\u00a0\u00a0\u00a09锛? 6" ,
ratios : [ "1080× 1920px\u00a0\u00a0\u00a09:1 6" ] ,
defaultRatio : "1080× 1920px\u00a0\u00a0\u00a09:1 6" ,
} ,
hot : {
ratios : [ "800脳 800px\u00a0\u00a0\u00a01锛? " ] ,
defaultRatio : "800脳 800px\u00a0\u00a0\u00a01锛? " ,
ratios : [ "800× 800px\u00a0\u00a0\u00a01:1 " ] ,
defaultRatio : "800× 800px\u00a0\u00a0\u00a01:1 " ,
} ,
} ,
specs : [ "商品主图 800脳 800px锛? :1" ] ,
specs : [ "商品主图 800× 800px, 1 :1" ] ,
} ,
{
label : "Instagram" ,
ratios : [ "帖子 1080脳 1350px" , "帖子 1080脳 1080px" , "Stories / Reels 1080脳 1920px" , "头像 320脳 320px" ] ,
defaultRatio : "帖子 1080脳 1350px" ,
ratios : [ "帖子 1080× 1350px" , "帖子 1080× 1080px" , "Stories / Reels 1080× 1920px" , "头像 320× 320px" ] ,
defaultRatio : "帖子 1080× 1350px" ,
ratioGroups : {
set : {
ratios : [ "1080脳 1080px\u00a0\u00a0\u00a01锛? " , "1080脳 1350px\u00a0\u00a0\u00a04锛? " ] ,
defaultRatio : "1080脳 1080px\u00a0\u00a0\u00a01锛? " ,
ratios : [ "1080× 1080px\u00a0\u00a0\u00a01:1 " , "1080× 1350px\u00a0\u00a0\u00a04:5 " ] ,
defaultRatio : "1080× 1080px\u00a0\u00a0\u00a01:1 " ,
} ,
detail : {
ratios : [ "1080脳 1350px\u00a0\u00a0\u00a04锛? " ] ,
defaultRatio : "1080脳 1350px\u00a0\u00a0\u00a04锛? " ,
ratios : [ "1080× 1350px\u00a0\u00a0\u00a04:5 " ] ,
defaultRatio : "1080× 1350px\u00a0\u00a0\u00a04:5 " ,
} ,
model : {
ratios : [ "1080脳 1350px\u00a0\u00a0\u00a04锛? " ] ,
defaultRatio : "1080脳 1350px\u00a0\u00a0\u00a04锛? " ,
ratios : [ "1080× 1350px\u00a0\u00a0\u00a04:5 " ] ,
defaultRatio : "1080× 1350px\u00a0\u00a0\u00a04:5 " ,
} ,
video : {
ratios : [ "1080脳 1920px\u00a0\u00a0\u00a09锛? 6" , "1080脳 1350px\u00a0\u00a0\u00a04锛? " ] ,
defaultRatio : "1080脳 1920px\u00a0\u00a0\u00a09锛? 6" ,
ratios : [ "1080× 1920px\u00a0\u00a0\u00a09:1 6" , "1080× 1350px\u00a0\u00a0\u00a04:5 " ] ,
defaultRatio : "1080× 1920px\u00a0\u00a0\u00a09:1 6" ,
} ,
} ,
specs : [ "帖子 1080脳 1350px 或? 1080脳 1080px" , "Stories / Reels 封面 1080脳 1920px锛屽ご鍍? 320脳 320px" ] ,
tip : "建议 鈮? MB JPG銆? " ,
specs : [ "帖子 1080× 1350px 或 1080× 1080px" , "Stories / Reels 封面 1080× 1920px,头像 320× 320px" ] ,
tip : "建议 ≤8 MB JPG。 " ,
aliases : [ "Instagram Reels" ] ,
} ,
{
label : "速卖通" ,
ratios : [ "主图 800脳 800px" , "主图 1000脳 1000px+" ] ,
defaultRatio : "主图 800脳 800px" ,
ratios : [ "主图 800× 800px" , "主图 1000× 1000px+" ] ,
defaultRatio : "主图 800× 800px" ,
ratioGroups : {
set : {
ratios : [ "1000脳 1000px\u00a0\u00a0\u00a01锛? " ] ,
defaultRatio : "1000脳 1000px\u00a0\u00a0\u00a01锛? " ,
ratios : [ "1000× 1000px\u00a0\u00a0\u00a01:1 " ] ,
defaultRatio : "1000× 1000px\u00a0\u00a0\u00a01:1 " ,
} ,
detail : {
ratios : [ "750脳 1125px\u00a0\u00a0\u00a02锛? " , "750脳 1000px\u00a0\u00a0\u00a03锛? " ] ,
defaultRatio : "750脳 1125px\u00a0\u00a0\u00a02锛? " ,
ratios : [ "750× 1125px\u00a0\u00a0\u00a02:3 " , "750× 1000px\u00a0\u00a0\u00a03:4 " ] ,
defaultRatio : "750× 1125px\u00a0\u00a0\u00a02:3 " ,
} ,
model : {
ratios : [ "750脳 1125px\u00a0\u00a0\u00a02锛? " ] ,
defaultRatio : "750脳 1125px\u00a0\u00a0\u00a02锛? " ,
ratios : [ "750× 1125px\u00a0\u00a0\u00a02:3 " ] ,
defaultRatio : "750× 1125px\u00a0\u00a0\u00a02:3 " ,
} ,
video : {
ratios : [ "1080脳 1920px\u00a0\u00a0\u00a09锛? 6" , "1920脳 1080px\u00a0\u00a0\u00a016锛? " ] ,
defaultRatio : "1080脳 1920px\u00a0\u00a0\u00a09锛? 6" ,
ratios : [ "1080× 1920px\u00a0\u00a0\u00a09:1 6" , "1920× 1080px\u00a0\u00a0\u00a016:9 " ] ,
defaultRatio : "1080× 1920px\u00a0\u00a0\u00a09:1 6" ,
} ,
hot : {
ratios : [ "800脳 800px\u00a0\u00a0\u00a01锛? " ] ,
defaultRatio : "800脳 800px\u00a0\u00a0\u00a01锛? " ,
ratios : [ "800× 800px\u00a0\u00a0\u00a01:1 " ] ,
defaultRatio : "800× 800px\u00a0\u00a0\u00a01:1 " ,
} ,
} ,
specs : [ "主图建议 800脳 800px 或更高,1:1" , "适合跨境电商主图、SKU 鍥惧拰鍦烘櫙鍥? " ] ,
specs : [ "主图建议 800× 800px 或更高,1:1" , "适合跨境电商主图、SKU 图和场景图 " ] ,
} ,
{
label : "eBay" ,
ratios : [ "鍟嗗搧鍥? 1:1" , "白底多角度展示图 1:1" ] ,
defaultRatio : "鍟嗗搧鍥? 1:1" ,
ratios : [ "商品图 1:1" , "白底多角度展示图 1:1" ] ,
defaultRatio : "商品图 1:1" ,
ratioGroups : {
set : {
ratios : [ "1600脳 1600px\u00a0\u00a0\u00a01锛? " ] ,
defaultRatio : "1600脳 1600px\u00a0\u00a0\u00a01锛? " ,
ratios : [ "1600× 1600px\u00a0\u00a0\u00a01:1 " ] ,
defaultRatio : "1600× 1600px\u00a0\u00a0\u00a01:1 " ,
} ,
detail : {
ratios : [ "1000脳 1500px\u00a0\u00a0\u00a02锛? " , "1200脳 1600px\u00a0\u00a0\u00a03锛? " ] ,
defaultRatio : "1000脳 1500px\u00a0\u00a0\u00a02锛? " ,
ratios : [ "1000× 1500px\u00a0\u00a0\u00a02:3 " , "1200× 1600px\u00a0\u00a0\u00a03:4 " ] ,
defaultRatio : "1000× 1500px\u00a0\u00a0\u00a02:3 " ,
} ,
model : {
ratios : [ "1000脳 1500px\u00a0\u00a0\u00a02锛? " ] ,
defaultRatio : "1000脳 1500px\u00a0\u00a0\u00a02锛? " ,
ratios : [ "1000× 1500px\u00a0\u00a0\u00a02:3 " ] ,
defaultRatio : "1000× 1500px\u00a0\u00a0\u00a02:3 " ,
} ,
video : {
ratios : [ "1920脳 1080px\u00a0\u00a0\u00a016锛? " , "1080脳 1920px\u00a0\u00a0\u00a09锛? 6" ] ,
defaultRatio : "1920脳 1080px\u00a0\u00a0\u00a016锛? " ,
ratios : [ "1920× 1080px\u00a0\u00a0\u00a016:9 " , "1080× 1920px\u00a0\u00a0\u00a09:1 6" ] ,
defaultRatio : "1920× 1080px\u00a0\u00a0\u00a016:9 " ,
} ,
hot : {
ratios : [ "1600脳 1600px\u00a0\u00a0\u00a01锛? " ] ,
defaultRatio : "1600脳 1600px\u00a0\u00a0\u00a01锛? " ,
ratios : [ "1600× 1600px\u00a0\u00a0\u00a01:1 " ] ,
defaultRatio : "1600× 1600px\u00a0\u00a0\u00a01:1 " ,
} ,
} ,
specs : [ "鍟嗗搧鍥惧缓璁?1:1锛屼富浣撴竻鏅板眳涓? " , "閫傚悎 白底主图鍜屽瑙掑害灞曠ず鍥? " ] ,
specs : [ "商品图建议 1:1,主体清晰居中 " , "适合 白底主图和多角度展示图 " ] ,
} ,
{
label : "TikTok Shop" ,
ratios : [ "商品主图 1:1" , "鐭棰? / 竖版封面 9:16" ] ,
ratios : [ "商品主图 1:1" , "短视频 / 竖版封面 9:16" ] ,
defaultRatio : "商品主图 1:1" ,
ratioGroups : {
set : {
ratios : [ "1280脳 1280px\u00a0\u00a0\u00a01锛? " ] ,
defaultRatio : "1280脳 1280px\u00a0\u00a0\u00a01锛? " ,
ratios : [ "1280× 1280px\u00a0\u00a0\u00a01:1 " ] ,
defaultRatio : "1280× 1280px\u00a0\u00a0\u00a01:1 " ,
} ,
detail : {
ratios : [ "1080脳 1350px\u00a0\u00a0\u00a04锛? " ] ,
defaultRatio : "1080脳 1350px\u00a0\u00a0\u00a04锛? " ,
ratios : [ "1080× 1350px\u00a0\u00a0\u00a04:5 " ] ,
defaultRatio : "1080× 1350px\u00a0\u00a0\u00a04:5 " ,
} ,
model : {
ratios : [ "1080脳 1350px\u00a0\u00a0\u00a04锛? " ] ,
defaultRatio : "1080脳 1350px\u00a0\u00a0\u00a04锛? " ,
ratios : [ "1080× 1350px\u00a0\u00a0\u00a04:5 " ] ,
defaultRatio : "1080× 1350px\u00a0\u00a0\u00a04:5 " ,
} ,
video : {
ratios : [ "1080脳 1920px\u00a0\u00a0\u00a09锛? 6" ] ,
defaultRatio : "1080脳 1920px\u00a0\u00a0\u00a09锛? 6" ,
ratios : [ "1080× 1920px\u00a0\u00a0\u00a09:1 6" ] ,
defaultRatio : "1080× 1920px\u00a0\u00a0\u00a09:1 6" ,
} ,
hot : {
ratios : [ "800脳 800px\u00a0\u00a0\u00a01锛? " ] ,
defaultRatio : "800脳 800px\u00a0\u00a0\u00a01锛? " ,
ratios : [ "800× 800px\u00a0\u00a0\u00a01:1 " ] ,
defaultRatio : "800× 800px\u00a0\u00a0\u00a01:1 " ,
} ,
} ,
specs : [ "商品主图建议 1:1" , "鐭棰? 竖版封面建议 9:16" ] ,
specs : [ "商品主图建议 1:1" , "短视频 竖版封面建议 9:16" ] ,
} ,
] ;
const platformOptions = platformSpecOptions . map ( ( option ) = > option . label ) ;
@@ -684,7 +684,7 @@ const getPlatformLogoSources = (value: string) => {
if ( normalized . includes ( "shopee" ) ) return [ shopeeLogo ] ;
if ( normalized . includes ( "lazada" ) ) return [ lazadaLogo ] ;
if ( normalized . includes ( "instagram" ) ) return [ instagramLogo ] ;
if ( value . includes ( "速卖通" ) || value . includes ( "閫熷崠閫" ) ) return [ aliexpressLogo ] ;
if ( value . includes ( "速卖通" ) ) return [ aliexpressLogo ] ;
if ( normalized . includes ( "ebay" ) ) return [ ebayLogo ] ;
if ( normalized . includes ( "tiktok" ) ) return [ tiktokShopLogo ] ;
return [ ] ;
@@ -744,7 +744,7 @@ const languageAliases: Record<string, string> = {
"西班牙语" : "西班牙语" ,
"葡文" : "葡萄牙语" ,
"葡萄牙语" : "葡萄牙语" ,
"鍗板凹璇? " : "印度尼西亚语" ,
"印尼语 " : "印度尼西亚语" ,
"印度尼西亚语" : "印度尼西亚语" ,
"菲律宾语" : "菲律宾语(他加禄语)" ,
"菲律宾语(他加禄语)" : "菲律宾语(他加禄语)" ,
@@ -755,10 +755,10 @@ const getPlatformSpec = (value: string) =>
const legacyPlatformAliases : Record < string , string > = {
"淘宝/天猫" : "淘宝/天猫" ,
"京东" : "京东" ,
"鎷煎澶? " : "拼多多" ,
"拼多多 " : "拼多多" ,
"抖音电商" : "抖音电商" ,
"浜氶┈閫? Amazon" : "亚马逊 Amazon" ,
"閫熷崠閫? " : "速卖通" ,
"亚马逊 Amazon" : "亚马逊 Amazon" ,
"速卖通 " : "速卖通" ,
} ;
const normalizePlatform = ( value : string ) = > getPlatformSpec ( legacyPlatformAliases [ value ] ? ? value ) . label ;
const domesticPlatformLabels = new Set ( [ "淘宝/天猫" , "京东" , "拼多多" , "抖音电商" ] ) ;
@@ -811,13 +811,13 @@ const formatRatioDisplayValue = (value: string) => {
return ` ${ width } × ${ height } px \ u00a0 \ u00a0 \ u00a0 ${ formatAspectRatio ( width , height ) } ` ;
}
return normalizedValue
. replace ( "淘宝主图 / SKU 鍥? " , "淘宝主图 / SKU 图 " )
. replace ( "京东主图 / SKU 鍥? " , "京东主图 / SKU 图 " )
. replace ( "淘宝主图 / SKU 图 " , "淘宝主图 / SKU 图 " )
. replace ( "京东主图 / SKU 图 " , "京东主图 / SKU 图 " )
. replace ( "详情页宽" , "详情页宽" )
. replace ( "鐭棰? " , "短视频" )
. replace ( "短视频 " , "短视频" )
. replace ( "主图" , "主图" )
. replace ( "商品主图" , "商品主图" )
. replace ( "鍟嗗搧鍥? " , "商品图" ) ;
. replace ( "商品图 " , "商品图" ) ;
} ;
/** Extract CSS aspect-ratio from a ratio string like "1000x1000px 1:1" -> "1 / 1" */
const parseRatioToAspectCss = ( ratioStr : string ) : string = > {
@@ -825,7 +825,7 @@ const parseRatioToAspectCss = (ratioStr: string): string => {
if ( ! match ) return "1 / 1" ;
return ` ${ match [ 1 ] } / ${ match [ 2 ] } ` ;
} ;
/** Normalize ratio display string ("1000脳 1000px 1锛? ") to API format ("1:1") */
/** Normalize ratio display string ("1000× 1000px 1:1 ") to API format ("1:1") */
const normalizeRatioForApi = ( ratioStr : string ) : string = > {
const match = ratioStr . match ( / ( \ d + ) \ D + ( \ d + ) / u ) ;
if ( ! match ) return "1:1" ;
@@ -938,7 +938,7 @@ const productSetAssets = ossAssets.ecommerce.productSet;
const productSetPreviewCards = [
{ id : "main" , label : "01 主图 (白底/合规)" , src : productSetAssets.main } ,
{ id : "scene" , label : "02 场景展示" , src : productSetAssets.scene } ,
{ id : "model" , label : "03 妯$壒鍦烘櫙鍥? " , src : productSetAssets.model } ,
{ id : "model" , label : "03 模特场景图 " , src : productSetAssets.model } ,
{ id : "detail" , label : "04 细节说明" , src : productSetAssets.detail } ,
{ id : "selling" , label : "05 卖点详解" , src : productSetAssets.selling } ,
] ;
@@ -998,6 +998,22 @@ function getImageFileFormat(file: File) {
return file . name . split ( "." ) . pop ( ) ? . toUpperCase ( ) ? ? "" ;
}
function getRemoteImageFormat ( mimeType : string , imageUrl : string ) {
const mimeFormat = mimeType . split ( "/" ) [ 1 ] ? . replace ( "jpeg" , "jpg" ) . toUpperCase ( ) ;
if ( mimeFormat ) return mimeFormat ;
return imageUrl . split ( "?" ) [ 0 ] . split ( "." ) . pop ( ) ? . toUpperCase ( ) ? ? "IMAGE" ;
}
function getRemoteImageName ( imageUrl : string , fallback : string ) {
try {
const parsed = new URL ( imageUrl ) ;
const filename = decodeURIComponent ( parsed . pathname . split ( "/" ) . filter ( Boolean ) . pop ( ) || "" ) ;
return filename || fallback ;
} catch {
return fallback ;
}
}
function readImageDimensions ( src : string ) : Promise < { width : number ; height : number } > {
return new Promise ( ( resolve , reject ) = > {
const image = new Image ( ) ;
@@ -1219,7 +1235,9 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
const cloneReferenceInputRef = useRef < HTMLInputElement > ( null ) ;
const smartCutoutInputRef = useRef < HTMLInputElement > ( null ) ;
const imageWorkbenchInputRef = useRef < HTMLInputElement > ( null ) ;
const imageWorkbenchUrlInputRef = useRef < HTMLInputElement > ( null ) ;
const watermarkInputRef = useRef < HTMLInputElement > ( null ) ;
const watermarkUrlInputRef = useRef < HTMLInputElement > ( null ) ;
const watermarkProcessTimeoutRef = useRef < number | null > ( null ) ;
const smartCutoutTransitionTimeoutRef = useRef < number | null > ( null ) ;
const smartCutoutPendingUrlsRef = useRef < string [ ] > ( [ ] ) ;
@@ -1698,7 +1716,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
} ) ;
setProductSetStatus ( "ready" ) ;
} catch ( err ) {
toast . error ( err instanceof Error ? err . message : "鍟嗗搧鍥句笂浼犲け璐? " ) ;
toast . error ( err instanceof Error ? err . message : "商品图上传失败 " ) ;
}
} ;
@@ -1793,6 +1811,49 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
setIsCloneSettingsCollapsed ( false ) ;
} ;
const loadRemoteImageFromInput = async ( input : HTMLInputElement | null , fallbackName : string ) = > {
const rawValue = input ? . value . trim ( ) ? ? "" ;
if ( ! rawValue ) {
toast . info ( "请先粘贴图片 URL" ) ;
return null ;
}
let imageUrl : string ;
try {
const parsed = new URL ( rawValue , window . location . href ) ;
if ( parsed . protocol !== "http:" && parsed . protocol !== "https:" ) {
throw new Error ( "仅支持 http 或 https 图片链接" ) ;
}
imageUrl = parsed . toString ( ) ;
} catch ( error ) {
toast . error ( error instanceof Error ? error . message : "图片 URL 不正确" ) ;
return null ;
}
try {
const response = await fetch ( imageUrl ) ;
if ( ! response . ok ) throw new Error ( ` 图片读取失败( ${ response . status } ) ` ) ;
const blob = await response . blob ( ) ;
if ( ! blob . type . startsWith ( "image/" ) ) throw new Error ( "链接内容不是图片" ) ;
const src = URL . createObjectURL ( blob ) ;
try {
await readImageDimensions ( src ) ;
} catch {
URL . revokeObjectURL ( src ) ;
throw new Error ( "图片无法预览,请换一个链接" ) ;
}
if ( input ) input . value = "" ;
return {
src ,
name : getRemoteImageName ( imageUrl , fallbackName ) ,
format : getRemoteImageFormat ( blob . type , imageUrl ) ,
} ;
} catch ( error ) {
toast . error ( error instanceof Error ? error . message : "图片导入失败" ) ;
return null ;
}
} ;
const closeWatermarkRemovalPage = ( ) = > {
if ( watermarkProcessTimeoutRef . current !== null ) {
window . clearTimeout ( watermarkProcessTimeoutRef . current ) ;
@@ -1846,6 +1907,18 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
if ( file ) addWatermarkImage ( file ) ;
} ;
const handleWatermarkUrlImport = async ( ) = > {
const nextImage = await loadRemoteImageFromInput ( watermarkUrlInputRef . current , "watermark-source" ) ;
if ( ! nextImage ) return ;
setWatermarkImage ( ( current ) = > {
if ( current ? . src ) URL . revokeObjectURL ( current . src ) ;
return nextImage ;
} ) ;
setWatermarkStatus ( "idle" ) ;
setActiveQuickTool ( "watermark" ) ;
toast . success ( "图片已导入" ) ;
} ;
const handleWatermarkGenerate = ( ) = > {
if ( ! watermarkImage || watermarkStatus === "processing" ) return ;
if ( watermarkProcessTimeoutRef . current !== null ) window . clearTimeout ( watermarkProcessTimeoutRef . current ) ;
@@ -1943,6 +2016,22 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
if ( file ) addImageWorkbenchImage ( file ) ;
} ;
const handleImageWorkbenchUrlImport = async ( ) = > {
const nextImage = await loadRemoteImageFromInput ( imageWorkbenchUrlInputRef . current , "image-workbench-source" ) ;
if ( ! nextImage ) return ;
setImageWorkbenchImage ( ( current ) = > {
if ( current ? . src ) URL . revokeObjectURL ( current . src ) ;
return nextImage ;
} ) ;
setImageWorkbenchStatus ( "idle" ) ;
setImageWorkbenchMaskStrokes ( [ ] ) ;
setImageWorkbenchBrushCursor ( null ) ;
clearImageWorkbenchMaskCanvas ( ) ;
imageWorkbenchActiveStrokeIdRef . current = null ;
setActiveQuickTool ( "image-edit" ) ;
toast . success ( "图片已导入" ) ;
} ;
const handleImageWorkbenchGenerate = ( ) = > {
if ( ! imageWorkbenchImage ) {
toast . info ( "请先上传图片" ) ;
@@ -2444,7 +2533,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
setStatus ( "ready" ) ;
setResults ( [ ] ) ;
} catch ( err ) {
toast . error ( err instanceof Error ? err . message : "鍟嗗搧鍥句笂浼犲け璐? " ) ;
toast . error ( err instanceof Error ? err . message : "商品图上传失败 " ) ;
}
} ;
@@ -2961,7 +3050,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
setGarmentImages ( ( current ) = > [ . . . current , . . . nextImages ] . slice ( 0 , 5 ) ) ;
setTryOnStatus ( "ready" ) ;
} catch ( err ) {
toast . error ( err instanceof Error ? err . message : "鏈嶉グ鍥句笂浼犲け璐? " ) ;
toast . error ( err instanceof Error ? err . message : "服饰图上传失败 " ) ;
}
} ) ( ) ;
event . target . value = "" ;
@@ -3011,7 +3100,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
setDetailStatus ( "ready" ) ;
setDetailResultUrl ( null ) ;
} catch ( err ) {
toast . error ( err instanceof Error ? err . message : "璇︽儏鍥句笂浼犲け璐? " ) ;
toast . error ( err instanceof Error ? err . message : "详情图上传失败 " ) ;
}
} ;
@@ -3040,9 +3129,9 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
const IMAGE_MODEL = "gpt-image-2" ;
const setCountLabels : Record < CloneSetCountKey , { label : string ; promptDesc : string } > = {
selling : { label : "鍗栫偣鍥? " , promptDesc : "selling-point infographic image highlighting core product advantages and detail close-ups" } ,
white : { label : "白底鍥? " , promptDesc : "clean white-background product photo showing the item from its best angle, studio lighting, no props" } ,
scene : { label : "鍦烘櫙鍥? " , promptDesc : "lifestyle scene image showing the product in a realistic usage environment with natural surroundings" } ,
selling : { label : "卖点图 " , promptDesc : "selling-point infographic image highlighting core product advantages and detail close-ups" } ,
white : { label : "白底图 " , promptDesc : "clean white-background product photo showing the item from its best angle, studio lighting, no props" } ,
scene : { label : "场景图 " , promptDesc : "lifestyle scene image showing the product in a realistic usage environment with natural surroundings" } ,
} ;
const buildDetailModulePrompt = ( moduleIds : string [ ] ) : string = > {
@@ -3182,7 +3271,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
imageGen . updateTask ( storeId , { status : "completed" , progress : 100 , resultUrl : persistedUrl } ) ;
} else {
generatedUrls . push ( "" ) ;
imageGen . updateTask ( storeId , { status : "failed" , error : "生成鏈繑鍥炵粨鏋? " } ) ;
imageGen . updateTask ( storeId , { status : "failed" , error : "生成未返回结果 " } ) ;
}
}
}
@@ -3270,7 +3359,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
imageGen . updateTask ( storeId , { status : "completed" , progress : 100 , resultUrl : persistedUrl } ) ;
} else {
statusFn ? . ( "idle" ) ;
imageGen . updateTask ( storeId , { status : "failed" , error : "生成鏈繑鍥炵粨鏋? " } ) ;
imageGen . updateTask ( storeId , { status : "failed" , error : "生成未返回结果 " } ) ;
}
} catch ( err ) {
if ( imageAbortRef . current . current ) {
@@ -3467,7 +3556,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
const handleDetailAiWrite = ( ) = > {
setDetailRequirement (
"1.产品名称:无线降噪蓝牙耳机\n2.鏍稿績鍗栫偣锛氫富鍔ㄩ檷鍣€? 4H续航、低延迟连接、舒适佩戴\n3.适用人群:通勤、办公、运动和旅行用户\n4.期望场景:地铁通勤、居家办公、户外运动\n5.鍏蜂綋参数锛氳摑鐗?.3銆両PX4闃叉按銆佸揩鍏? 0分钟使用2小时" ,
"1.产品名称:无线降噪蓝牙耳机\n2.核心卖点:主动降噪、2 4H续航、低延迟连接、舒适佩戴\n3.适用人群:通勤、办公、运动和旅行用户\n4.期望场景:地铁通勤、居家办公、户外运动\n5.具体参数:蓝牙5.3、IPX4防水、快充1 0分钟使用2小时" ,
) ;
} ;
@@ -3547,19 +3636,19 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
const isWatermarkTool = isCloneTool && activeQuickTool === "watermark" ;
const isImageEditTool = isCloneTool && activeQuickTool === "image-edit" ;
const isHotVideoTool = isCloneTool && activeQuickTool === "hot-video" ;
const pageLabel = isSetTool ? "商品套图" : isDetail ? "A+/璇︽儏椤? " : isTryOn ? "AI服饰穿戴" : activeToolMeta ? . label || "商品工具" ;
const pageLabel = isSetTool ? "商品套图" : isDetail ? "A+/详情页 " : isTryOn ? "AI服饰穿戴" : activeToolMeta ? . label || "商品工具" ;
const setPrimaryLabel =
setImages . length === 0
? "请先上传商品原图"
: productSetStatus === "generating"
? "生成涓? .."
? "生成中. .."
: "生成" + selectedProductSetOutput . label ;
const tryOnPrimaryLabel =
garmentImages . length === 0 ? "请先上传服装图片" : tryOnStatus === "generating" ? "生成涓? .." : "生成服饰穿戴鍥? " ;
garmentImages . length === 0 ? "请先上传服装图片" : tryOnStatus === "generating" ? "生成中. .." : "生成服饰穿戴图 " ;
const detailPrimaryLabel =
detailProductImages . length === 0 ? "请上传产品图" : detailStatus === "generating" ? "生成涓? .." : "生成A+璇︽儏椤? " ;
detailProductImages . length === 0 ? "请上传产品图" : detailStatus === "generating" ? "生成中. .." : "生成A+详情页 " ;
const clonePrimaryLabel =
productImages . length === 0 ? "请先上传商品原图" : status === "generating" ? "生成涓? .." : "生成" + selectedCloneOutput . label ;
productImages . length === 0 ? "请先上传商品原图" : status === "generating" ? "生成中. .." : "生成" + selectedCloneOutput . label ;
const setPreviewCards : CloneResult [ ] = [ ] ;
let setIndex = 0 ;
for ( const countKey of cloneSetCountKeys ) {
@@ -3693,7 +3782,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
if ( historyRefreshLockRef . current ) return ;
historyRefreshLockRef . current = true ;
setIsHistoryRefreshing ( true ) ;
setHistoryRefreshMessage ( "鍒锋柊涓? .." ) ;
setHistoryRefreshMessage ( "刷新中. .." ) ;
setHistoryRefreshStamp ( Date . now ( ) ) ;
window . setTimeout ( ( ) = > {
@@ -4023,7 +4112,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
value = { productSetRequirement }
onChange = { ( event ) = > setProductSetRequirement ( event . target . value ) }
maxLength = { 500 }
placeholder = "建议鍖呭惈浠ヤ笅淇℃伅锛氫骇鍝佸悕绉般€佹牳蹇冨崠鐐广€佹湡鏈涘満鏅€佸叿浣撳弬鏁? "
placeholder = "建议包含以下信息:产品名称、核心卖点、期望场景、具体参数 "
/ >
< button type = "button" className = "product-set-floating-submit" disabled = { ! canGenerateSet } onClick = { handleSetGenerate } >
{ productSetStatus === "generating" ? < LoadingOutlined / > : null }
@@ -4290,7 +4379,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
< span className = "clone-ai-flow-node__label" > 附 件 原 图 < / span >
< / div >
{ /* Connector —鍒嗘敮杩炴帴绾? */ }
{ /* Connector - branch lines */ }
< div className = "clone-ai-flow-connector" aria-hidden = "true" >
< div className = "clone-ai-flow-connector__trunk" / >
< div className = "clone-ai-flow-connector__branches" >
@@ -4503,7 +4592,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
< strong > 上 传 商 品 图 < / strong >
< / button >
{ productImages . length || videoOutfitVideoFile ? (
< div className = "ecom-command-asset-popover" aria-label = "宸蹭笂浼犵礌鏉? " >
< div className = "ecom-command-asset-popover" aria-label = "已上传素材 " >
{ productImages . map ( ( image ) = > (
< figure key = { image . id } className = "ecom-command-asset-thumb" >
< img src = { image . src } alt = { image . name || "上传图片" } / >
@@ -4675,7 +4764,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
) ;
const smartCutoutPreview = (
< main className = { ` ecom-smart-cutout-page ${ smartCutoutImage ? " is-editor" : " is-upload" } ${ isSmartCutoutTransitioning ? " is-transitioning" : "" } ` } aria-label = "智能抠图" >
< main key = { ` smart-cutout- ${ smartCutoutImage ? "editor" : "upload" } ` } className = { ` ecom-smart-cutout-page ecom-tool-page-enter ${ smartCutoutImage ? " is-editor" : " is-upload" } ${ isSmartCutoutTransitioning ? " is-transitioning" : "" } ` } aria-label = "智能抠图" >
< input
ref = { smartCutoutInputRef }
type = "file"
@@ -4950,7 +5039,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
) ;
const imageWorkbenchPreview = (
< main className = "ecom-image-workbench-page" aria-label = "图片修改局部重绘" >
< main key = "image-workbench" className = "ecom-image-workbench-page ecom-tool-page-enter " aria-label = "图片修改局部重绘" >
< input
ref = { imageWorkbenchInputRef }
type = "file"
@@ -5021,8 +5110,15 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
) }
< / div >
< div className = "ecom-image-workbench-url-row" >
< input placeholder = "粘贴图片 URL" aria-label = "粘贴图片 URL" / >
< button type = "button" onClick = { ( ) = > toast . info ( "请先使用本地上传" ) } > 添 加 < / button >
< input
ref = { imageWorkbenchUrlInputRef }
placeholder = "粘贴图片 URL"
aria - label = "粘贴图片 URL"
onKeyDown = { ( event ) = > {
if ( event . key === "Enter" ) void handleImageWorkbenchUrlImport ( ) ;
} }
/ >
< button type = "button" onClick = { ( ) = > void handleImageWorkbenchUrlImport ( ) } > 添 加 < / button >
< / div >
< / section >
@@ -5155,7 +5251,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
) ;
const watermarkPreview = (
< main className = "ecom-watermark-page" aria-label = "去水印" >
< main key = "watermark" className = "ecom-watermark-page ecom-tool-page-enter " aria-label = "去水印" >
< input
ref = { watermarkInputRef }
type = "file"
@@ -5165,7 +5261,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
/ >
< aside className = "ecom-watermark-side" >
< header className = "ecom-quick-set-panel-head ecom-watermark-panel-head" >
< strong className = "ecom-quick-set-page-title" > 增 / 去 水 印 < / strong >
< strong className = "ecom-quick-set-page-title" > 去 水 印 < / strong >
< button type = "button" className = "ecom-quick-set-back" onClick = { closeWatermarkRemovalPage } > 首 页 < / button >
< button type = "button" className = "ecom-quick-set-back" onClick = { closeWatermarkRemovalPage } > 上 一 页 < / button >
< / header >
@@ -5225,8 +5321,15 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
) }
< / div >
< div className = "ecom-watermark-url-row" >
< input placeholder = "粘贴图片 URL" aria-label = "粘贴图片 URL" / >
< button type = "button" onClick = { ( ) = > toast . info ( "请先使用本地上传" ) } > 导 入 < / button >
< input
ref = { watermarkUrlInputRef }
placeholder = "粘贴图片 URL"
aria - label = "粘贴图片 URL"
onKeyDown = { ( event ) = > {
if ( event . key === "Enter" ) void handleWatermarkUrlImport ( ) ;
} }
/ >
< button type = "button" onClick = { ( ) = > void handleWatermarkUrlImport ( ) } > 导 入 < / button >
< / div >
< / section >
@@ -5350,7 +5453,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
) ;
const hotVideoPreview = (
< main className = "ecom-quick-set-page ecom-hot-video-page" aria-label = "广告视频" >
< main key = "hot-video" className = "ecom-quick-set-page ecom-hot-video-page ecom-tool-page-enter " aria-label = "广告视频" >
< div className = "ecom-quick-set-body" >
< aside className = "ecom-quick-set-panel" aria-label = "广告视频设置" >
< header className = "ecom-quick-set-panel-head" >
@@ -5475,7 +5578,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
) ;
const quickProductSetPreview = (
< main className = { ` ecom-quick-set-page ${ isQuickPanelCollapsed ? " is-panel-collapsed" : "" } ` } aria-label = "AI商品套图" >
< main key = "quick-set" className = { ` ecom-quick-set-page ecom-tool-page-enter ${ isQuickPanelCollapsed ? " is-panel-collapsed" : "" } ` } aria-label = "AI商品套图" >
< div className = "ecom-quick-set-body" >
< aside className = "ecom-quick-set-panel" aria-label = "商品套图设置" onWheel = { handleQuickPanelWheel } >
< header className = "ecom-quick-set-panel-head" >
@@ -5621,14 +5724,6 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
< / section >
< / section >
< / div >
< button
type = "button"
className = "ecom-quick-set-collapse"
aria - label = { isQuickPanelCollapsed ? "展开设置" : "收起设置" }
onClick = { ( ) = > setIsQuickPanelCollapsed ( ( value ) = > ! value ) }
>
{ isQuickPanelCollapsed ? "› " : "‹ " }
< / button >
< button type = "button" className = "ecom-quick-set-help" aria-label = "帮助" onClick = { ( ) = > toast . info ( "上传商品原图后,可选择平台、语言、比例并开始生成。" ) } > ? < / button >
< / main >
) ;
@@ -5636,7 +5731,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
const quickDetailVisibleSelect = quickDetailBasicSelects . find ( ( item ) = > item . key === visibleQuickSetSelect ) ? ? null ;
const quickDetailPreview = (
< main className = { ` ecom-quick-set-page ecom-quick-detail-page ${ isQuickPanelCollapsed ? " is-panel-collapsed" : "" } ` } aria-label = "A+详情页生成" >
< main key = "quick-detail" className = { ` ecom-quick-set-page ecom-quick-detail-page ecom-tool-page-enter ${ isQuickPanelCollapsed ? " is-panel-collapsed" : "" } ` } aria-label = "A+详情页生成" >
< div className = "ecom-quick-set-body" >
< aside className = "ecom-quick-set-panel" aria-label = "A+详情页设置" onWheel = { handleQuickPanelWheel } >
< header className = "ecom-quick-set-panel-head" >
@@ -5794,14 +5889,6 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
< / section >
< / section >
< / div >
< button
type = "button"
className = "ecom-quick-set-collapse"
aria - label = { isQuickPanelCollapsed ? "展开设置" : "收起设置" }
onClick = { ( ) = > setIsQuickPanelCollapsed ( ( value ) = > ! value ) }
>
{ isQuickPanelCollapsed ? "› " : "‹ " }
< / button >
< button type = "button" className = "ecom-quick-set-help" aria-label = "帮助" onClick = { ( ) = > toast . info ( "上传商品图后,选择平台和详情模块即可生成 A+ 详情页。" ) } > ? < / button >
< / main >
) ;
@@ -5930,7 +6017,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
? smartCutoutPreview
: isQuickSetTool || isQuickDetailTool || isHotVideoTool
? (
< div className = "ecom-quick-page-wrap" >
< div key = { ` quick- ${ activeQuickTool } ` } className = "ecom-quick-page-wrap ecom-tool-page-enter " >
{ quickPageSidebar }
{ isQuickSetTool ? quickProductSetPreview : isQuickDetailTool ? quickDetailPreview : hotVideoPreview }
< / div >
@@ -5948,7 +6035,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
return (
< section
className = { ` product-clone-page page-motion ${ isCloneTool && isCloneSettingsCollapsed ? " is-settings-collapsed" : "" } ${ isCloneTool && isCommandHistoryCollapsed ? " is-history-collapsed" : "" } ${ isSmartCutoutTool ? " is-smart-cutout-page" : "" } ${ isQuickSetTool || isQuickDetailTool ? " is-quick-set-page" : "" } ${ isWatermarkTool ? " is-watermark-page" : "" } ${ isImageEditTool ? " is-image-workbench-page" : "" } ${ isHotVideoTool ? " is-hot-video-page" : "" } ` }
className = { ` product-clone-page page-motion ${ isCloneTool && isCloneSettingsCollapsed ? " is-settings-collapsed" : "" } ${ isCloneTool && isCommandHistoryCollapsed ? " is-history-collapsed" : "" } ${ isSmartCutoutTool ? " is-smart-cutout-page" : "" } ${ isQuickSetTool || isQuickDetailTool || isHotVideoTool ? " is-quick-set-page" : "" } ${ isWatermarkTool ? " is-watermark-page" : "" } ${ isImageEditTool ? " is-image-workbench-page" : "" } ${ isHotVideoTool ? " is-hot-video-page" : "" } ` }
data - tool = { activeTool }
aria - label = { pageLabel }
>
@@ -5994,7 +6081,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
productImageFiles = { ecommerceVideoImageFiles }
requirement = { requirement }
platform = { platform }
aspectRatio = { ratio . includes ( "9锛? 6" ) || ratio . includes ( "9:16" ) ? "9:16" : ratio . includes ( "16锛? " ) || ratio . includes ( "16:9" ) ? "16:9" : ratio . includes ( "3锛? " ) || ratio . includes ( "3:4" ) ? "3:4" : "9:16" }
aspectRatio = { ratio . includes ( "9:1 6" ) || ratio . includes ( "9:16" ) ? "9:16" : ratio . includes ( "16:9 " ) || ratio . includes ( "16:9" ) ? "16:9" : ratio . includes ( "3:4 " ) || ratio . includes ( "3:4" ) ? "3:4" : "9:16" }
durationSeconds = { cloneVideoDuration }
resolution = { cloneVideoQuality === "standard" ? "720P" : "1080P" }
onRequestLogin = { ( ) = > ( isAuthenticated ? undefined : requestLogin ( ) ) }