feat: 新增电商灵感实验室模块,包含AI团队/电商套图/商品视频分类卡片
新增功能: - 新增电商灵感案例区域(ecom-inspiration-lab),含6个分类标签页(最近打开/一键同款/海报模板/热门/商品图/模特穿戴) - 新增三个灵感分类行: · AI团队:指定ASIN优化listing、TikTok美区爆品分析、竞品分析+全套listing、世界杯属性快闪视频 · 电商套图:科技礼盒主图、美妆节日套图、防晒产品场景、露营家具详情、香氛A+页面、童装listing组合 · 商品视频:口播种草短片、香水质感视频、玩具互动短视频、器皿产品展示、饰品模特试戴、包袋生活方式 - 每行卡片支持横向滚动,配备左右箭头按钮控制浏览 - 仅在非完成(status !== 'done')状态下展示灵感区域 样式更新: - ecommerce-standalone.css 新增灵感实验室全套样式,包括标签页导航、分类行元信息、卡片网格布局、横向滚动条、滚动按钮等组件的视觉设计 - 适配暗色主题变量体系,保持与现有设计系统一致 变更文件: - src/features/ecommerce/EcommercePage.tsx (+92/-2) - src/styles/ecommerce-standalone.css (+1136)
This commit is contained in:
@@ -101,6 +101,48 @@ const smartCutoutSizeOptions = [
|
|||||||
type SmartCutoutSizeKey = (typeof smartCutoutSizeOptions)[number]["key"];
|
type SmartCutoutSizeKey = (typeof smartCutoutSizeOptions)[number]["key"];
|
||||||
type SmartCutoutImageItem = { src: string; name: string; originalSrc?: string };
|
type SmartCutoutImageItem = { src: string; name: string; originalSrc?: string };
|
||||||
|
|
||||||
|
const ecommerceInspirationTabs = ["最近打开", "一键同款", "海报模板", "热门", "商品图", "模特穿戴"];
|
||||||
|
|
||||||
|
const ecommerceInspirationRows = [
|
||||||
|
{
|
||||||
|
title: "AI团队",
|
||||||
|
desc: "不止作图,更懂转化。",
|
||||||
|
variant: "team",
|
||||||
|
cards: [
|
||||||
|
{ title: "指定ASIN,优化listing", meta: "竞品拆解 · 卖点重排 · 图文建议" },
|
||||||
|
{ title: "TikTok美区爆品分析", meta: "脚本方向 · 人群洞察 · 素材策略" },
|
||||||
|
{ title: "竞品分析 + 全套listing", meta: "关键词 · 主图结构 · 转化建议" },
|
||||||
|
{ title: "世界杯属性快闪视频", meta: "热点追踪 · 模板复用 · 15秒短片" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "电商套图",
|
||||||
|
desc: "主图 / 详情图全套一次性生成。",
|
||||||
|
variant: "listing",
|
||||||
|
cards: [
|
||||||
|
{ title: "科技礼盒主图", meta: "高反差质感 · 参数卖点" },
|
||||||
|
{ title: "美妆节日套图", meta: "促销氛围 · 多规格展示" },
|
||||||
|
{ title: "防晒产品场景", meta: "户外光感 · 功效表达" },
|
||||||
|
{ title: "露营家具详情", meta: "场景组合 · 尺寸说明" },
|
||||||
|
{ title: "香氛A+页面", meta: "材质细节 · 品牌氛围" },
|
||||||
|
{ title: "童装listing组合", meta: "多角度 · 人群展示" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "商品视频",
|
||||||
|
desc: "口播模拟 / 商品展示视频 / 社媒短片。",
|
||||||
|
variant: "video",
|
||||||
|
cards: [
|
||||||
|
{ title: "口播种草短片", meta: "手持展示 · 真实推荐" },
|
||||||
|
{ title: "香水质感视频", meta: "光影旋转 · 高级静物" },
|
||||||
|
{ title: "玩具互动短视频", meta: "生活场景 · 情绪表达" },
|
||||||
|
{ title: "器皿产品展示", meta: "极简背景 · 材质突出" },
|
||||||
|
{ title: "饰品模特试戴", meta: "近景特写 · 搭配建议" },
|
||||||
|
{ title: "包袋生活方式", meta: "室内场景 · 组合展示" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
] as const;
|
||||||
|
|
||||||
const clampNumber = (value: number, min: number, max: number) => Math.min(max, Math.max(min, value));
|
const clampNumber = (value: number, min: number, max: number) => Math.min(max, Math.max(min, value));
|
||||||
|
|
||||||
const normalizeHexColor = (value: string) => {
|
const normalizeHexColor = (value: string) => {
|
||||||
@@ -4180,6 +4222,13 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
|
|||||||
handleGenerate();
|
handleGenerate();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const scrollInspirationRow = (event: ReactMouseEvent<HTMLButtonElement>, direction: -1 | 1) => {
|
||||||
|
const row = event.currentTarget.closest(".ecom-inspiration-row");
|
||||||
|
const strip = row?.querySelector<HTMLElement>(".ecom-inspiration-strip");
|
||||||
|
if (!strip) return;
|
||||||
|
strip.scrollBy({ left: direction * Math.max(280, strip.clientWidth * 0.78), behavior: "smooth" });
|
||||||
|
};
|
||||||
|
|
||||||
const clonePreview = (
|
const clonePreview = (
|
||||||
<main className="product-clone-preview clone-ai-preview" data-status={status} aria-label="电商 AI 作图预览" {...getPreviewSurfaceProps()}>
|
<main className="product-clone-preview clone-ai-preview" data-status={status} aria-label="电商 AI 作图预览" {...getPreviewSurfaceProps()}>
|
||||||
<header className="clone-ai-preview-header">
|
<header className="clone-ai-preview-header">
|
||||||
@@ -4551,7 +4600,46 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
|
|||||||
))}
|
))}
|
||||||
</section>
|
</section>
|
||||||
) : null}
|
) : null}
|
||||||
<span className="clone-ai-char-count">{requirement.length}/500</span>
|
{status !== "done" ? (
|
||||||
|
<section className="ecom-inspiration-lab" aria-label="电商灵感案例">
|
||||||
|
<nav className="ecom-inspiration-tabs" aria-label="案例分类">
|
||||||
|
{ecommerceInspirationTabs.map((tab, index) => (
|
||||||
|
<button key={tab} type="button" className={index === 3 ? "is-active" : ""}>
|
||||||
|
{tab}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
<div className="ecom-inspiration-rows">
|
||||||
|
{ecommerceInspirationRows.map((row) => (
|
||||||
|
<section key={row.title} className={`ecom-inspiration-row ecom-inspiration-row--${row.variant}`} aria-label={row.title}>
|
||||||
|
<div className="ecom-inspiration-row__meta">
|
||||||
|
<strong>{row.title}</strong>
|
||||||
|
<span>{row.desc}</span>
|
||||||
|
<div className="ecom-inspiration-row__controls">
|
||||||
|
<button type="button" aria-label={`向左浏览${row.title}`} onClick={(event) => scrollInspirationRow(event, -1)}>‹</button>
|
||||||
|
<button type="button" aria-label={`向右浏览${row.title}`} onClick={(event) => scrollInspirationRow(event, 1)}>›</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="ecom-inspiration-strip" tabIndex={0}>
|
||||||
|
{row.cards.map((card, index) => (
|
||||||
|
<article key={card.title} className="ecom-inspiration-card">
|
||||||
|
<div className="ecom-inspiration-card__visual" aria-hidden="true">
|
||||||
|
<span />
|
||||||
|
<span />
|
||||||
|
<span />
|
||||||
|
<span />
|
||||||
|
</div>
|
||||||
|
<strong>{card.title}</strong>
|
||||||
|
<p>{card.meta}</p>
|
||||||
|
<em>{String(index + 1).padStart(2, "0")}</em>
|
||||||
|
</article>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
) : null}
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
@@ -5919,7 +6007,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
|
|||||||
aria-label={isCommandHistoryCollapsed ? "展开记录" : "收起记录"}
|
aria-label={isCommandHistoryCollapsed ? "展开记录" : "收起记录"}
|
||||||
aria-expanded={!isCommandHistoryCollapsed}
|
aria-expanded={!isCommandHistoryCollapsed}
|
||||||
>
|
>
|
||||||
{isCommandHistoryCollapsed ? "‹" : "›"}
|
{isCommandHistoryCollapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
|
||||||
</button>
|
</button>
|
||||||
<button type="button" className="ecom-command-history__new" onClick={handleNewEcommerceConversation}>新对话</button>
|
<button type="button" className="ecom-command-history__new" onClick={handleNewEcommerceConversation}>新对话</button>
|
||||||
<button
|
<button
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user