chore: 全量推送 · 累积页面改动 + Next.js 工程骨架 + v1/ 归档 + 文档
页面 (电商AI平台/) - account / team / settings / index / products / projects: 累积迭代 - restraint.css: 设计 token 补充 - login.html / register.html: 新增登录注册页 - _ARCHIVE.md: 归档说明 Next.js 工程骨架 - app/ + components/: 新一代 SPA 雏形 (page / layout / sidebar / topbar / GridBg / Icon) - package.json / package-lock.json / next.config.mjs / tsconfig.json / postcss.config.mjs / next-env.d.ts 历史归档 / 文档 - v1/: 原 V1 静态稿镜像 (含 mockup-A/B/C) - PRD.md / deployment-guide.md / _check.html - ui参考/ / screenshots/ 杂项 - .gitignore 调整 - 删除根 README.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,495 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>新建商品 · 三版交互方案对比 · 流·Studio</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="../assets/restraint.css">
|
||||
<style>
|
||||
body { background: var(--bg); padding: 40px 24px 80px; }
|
||||
.wrap { max-width: 1200px; margin: 0 auto; }
|
||||
|
||||
.head { margin-bottom: 36px; padding-bottom: 24px; border-bottom: 1px solid var(--border); position: relative; }
|
||||
.head::before { content: '+'; position: absolute; top: -8px; left: -8px; color: var(--ink-3); font-family: 'JetBrains Mono', monospace; font-size: 12px; }
|
||||
.head h1 { font-size: 28px; font-weight: 700; letter-spacing: -.018em; }
|
||||
.head .sub { font-size: 13.5px; color: var(--ink-2); margin-top: 8px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
|
||||
.head .sub .mono { font-family: 'JetBrains Mono', monospace; font-size: 11.5px; color: var(--ink-3); letter-spacing: .04em; }
|
||||
|
||||
.ctx-box {
|
||||
background: var(--card); border: 1px solid var(--border); padding: 18px 22px;
|
||||
margin-bottom: 28px; position: relative;
|
||||
}
|
||||
.ctx-box::before, .ctx-box::after { content: '+'; position: absolute; color: var(--ink-3); font-family: 'JetBrains Mono', monospace; font-size: 12px; }
|
||||
.ctx-box::before { top: -7px; left: -7px; }
|
||||
.ctx-box::after { bottom: -7px; right: -7px; }
|
||||
.ctx-box h3 { font-size: 13px; font-weight: 600; margin-bottom: 8px; }
|
||||
.ctx-box p { font-size: 12.5px; color: var(--ink-2); line-height: 1.7; }
|
||||
.ctx-box .flow-line {
|
||||
margin-top: 14px;
|
||||
padding: 12px 14px;
|
||||
background: var(--bg-soft);
|
||||
border: 1px solid var(--border-soft);
|
||||
font-family: 'JetBrains Mono', monospace; font-size: 11.5px;
|
||||
color: var(--ink-2); letter-spacing: .02em;
|
||||
line-height: 1.8;
|
||||
}
|
||||
.ctx-box .flow-line .arrow { color: var(--orange); margin: 0 6px; }
|
||||
|
||||
.versions { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
|
||||
.ver-card {
|
||||
background: var(--card); border: 1px solid var(--border);
|
||||
display: flex; flex-direction: column;
|
||||
text-decoration: none; color: var(--ink);
|
||||
transition: border-color .15s;
|
||||
position: relative;
|
||||
}
|
||||
.ver-card:hover { border-color: var(--orange); }
|
||||
.ver-card:hover::before, .ver-card:hover::after { color: var(--orange); }
|
||||
.ver-card::before, .ver-card::after { content: '+'; position: absolute; color: var(--ink-3); font-family: 'JetBrains Mono', monospace; font-size: 12px; transition: color .15s; }
|
||||
.ver-card::before { top: -7px; left: -7px; }
|
||||
.ver-card::after { bottom: -7px; right: -7px; }
|
||||
|
||||
.ver-preview {
|
||||
aspect-ratio: 4/3;
|
||||
background:
|
||||
repeating-linear-gradient(135deg, rgba(0,0,0,0.02) 0 1px, transparent 1px 12px),
|
||||
var(--bg-soft);
|
||||
border-bottom: 1px solid var(--border);
|
||||
position: relative;
|
||||
padding: 14px;
|
||||
}
|
||||
.ver-preview .mock { position: absolute; inset: 14px; background: var(--card); border: 1px solid var(--border); display: flex; flex-direction: column; }
|
||||
|
||||
/* Mock A: stepper */
|
||||
.mock-A-top { padding: 8px; border-bottom: 1px solid var(--border); display: flex; justify-content: center; gap: 8px; }
|
||||
.mock-A-top span { width: 12px; height: 12px; background: var(--bg-soft); border: 1px solid var(--border); }
|
||||
.mock-A-top span:nth-child(2) { background: var(--orange); border-color: var(--orange); }
|
||||
.mock-A-body { flex: 1; display: grid; grid-template-columns: 1fr 1fr; gap: 6px; padding: 10px; }
|
||||
.mock-A-body div { background: var(--bg-soft); border: 1px solid var(--border); }
|
||||
.mock-A-body div.sel { background: var(--orange-tint); border-color: var(--orange); }
|
||||
.mock-A-foot { padding: 6px 10px; border-top: 1px solid var(--border); display: flex; justify-content: space-between; }
|
||||
.mock-A-foot span { width: 28px; height: 8px; background: var(--bg-soft); border: 1px solid var(--border); }
|
||||
.mock-A-foot span.primary { background: var(--orange); border-color: var(--orange); }
|
||||
|
||||
/* Mock B: accordion */
|
||||
.mock-B-top { padding: 6px 8px; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 4px; }
|
||||
.mock-B-top .bar { flex: 1; height: 3px; background: var(--bg-soft); }
|
||||
.mock-B-top .bar span { display: block; width: 50%; height: 100%; background: var(--orange); }
|
||||
.mock-B-rows { flex: 1; display: flex; flex-direction: column; padding: 6px; gap: 4px; }
|
||||
.mock-B-row { padding: 6px 8px; background: var(--bg-soft); border: 1px solid var(--border); display: flex; align-items: center; gap: 6px; }
|
||||
.mock-B-row.done .num { background: var(--ink); color: #FFF; }
|
||||
.mock-B-row.active { background: var(--orange-tint); border-color: var(--orange); padding: 8px; flex: 1; }
|
||||
.mock-B-row .num { width: 14px; height: 14px; background: var(--card); border: 1px solid var(--border); font-size: 8px; display: grid; place-items: center; font-family: 'JetBrains Mono', monospace; }
|
||||
.mock-B-row.active .num { background: var(--orange); color: #FFF; border-color: var(--orange); }
|
||||
.mock-B-row .lbl { flex: 1; height: 6px; background: var(--card); border: 1px solid var(--border); }
|
||||
|
||||
/* Mock C: workbench */
|
||||
.mock-C-top { padding: 6px 8px; border-bottom: 1px solid var(--border); }
|
||||
.mock-C-top .ti { width: 60%; height: 6px; background: var(--bg-soft); }
|
||||
.mock-C-body { flex: 1; display: grid; grid-template-columns: 36px 1fr 50px; gap: 0; }
|
||||
.mock-C-side { background: var(--bg-soft); border-right: 1px solid var(--border); padding: 6px; display: flex; flex-direction: column; gap: 4px; }
|
||||
.mock-C-side div { width: 100%; height: 8px; background: var(--card); border: 1px solid var(--border); }
|
||||
.mock-C-side div.act { background: var(--orange); border-color: var(--orange); }
|
||||
.mock-C-canvas { padding: 8px; display: grid; grid-template-columns: 1fr 1fr; gap: 4px; }
|
||||
.mock-C-canvas div { background: var(--bg-soft); border: 1px solid var(--border); }
|
||||
.mock-C-canvas div.sel { background: var(--orange-tint); border-color: var(--orange); }
|
||||
.mock-C-controls { background: var(--bg-soft); border-left: 1px solid var(--border); padding: 6px; display: flex; flex-direction: column; gap: 4px; }
|
||||
.mock-C-controls div { background: var(--card); border: 1px solid var(--border); height: 14px; }
|
||||
|
||||
.ver-info { padding: 18px 20px; }
|
||||
.ver-info .badge {
|
||||
display: inline-block;
|
||||
font-family: 'JetBrains Mono', monospace; font-size: 10.5px;
|
||||
color: var(--orange); background: var(--orange-tint); border: 1px solid var(--orange-soft);
|
||||
padding: 2px 8px; letter-spacing: .04em;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.ver-info h2 { font-size: 16px; font-weight: 700; margin-bottom: 6px; }
|
||||
.ver-info .tagline { font-size: 12.5px; color: var(--ink-2); line-height: 1.6; margin-bottom: 14px; }
|
||||
.ver-info ul { list-style: none; padding: 0; }
|
||||
.ver-info ul li { font-size: 11.5px; color: var(--ink-2); padding: 5px 0; display: flex; gap: 8px; align-items: flex-start; }
|
||||
.ver-info ul li::before { content: ''; width: 5px; height: 5px; background: var(--orange); border-radius: 50%; margin-top: 7px; flex-shrink: 0; }
|
||||
.ver-info .cta { margin-top: 16px; }
|
||||
|
||||
.ver-info .pros, .ver-info .cons { margin-top: 12px; padding: 10px 12px; font-size: 11.5px; line-height: 1.6; }
|
||||
.ver-info .pros { background: var(--green-bg); border: 1px solid var(--green-bd); color: var(--green); }
|
||||
.ver-info .cons { background: var(--bg-soft); border: 1px solid var(--border); color: var(--ink-2); }
|
||||
.ver-info .pros strong, .ver-info .cons strong { font-family: 'JetBrains Mono', monospace; font-size: 10px; letter-spacing: .04em; display: block; margin-bottom: 3px; }
|
||||
|
||||
.compare-table {
|
||||
margin-top: 36px;
|
||||
background: var(--card); border: 1px solid var(--border);
|
||||
position: relative;
|
||||
}
|
||||
.compare-table::before, .compare-table::after { content: '+'; position: absolute; color: var(--ink-3); font-family: 'JetBrains Mono', monospace; font-size: 12px; }
|
||||
.compare-table::before { top: -7px; left: -7px; }
|
||||
.compare-table::after { bottom: -7px; right: -7px; }
|
||||
.compare-table h3 { padding: 14px 18px; border-bottom: 1px solid var(--border); font-size: 14px; font-weight: 600; }
|
||||
table.cmp { width: 100%; border-collapse: collapse; }
|
||||
table.cmp th { text-align: left; padding: 12px 18px; background: var(--bg-soft); font-family: 'JetBrains Mono', monospace; font-size: 10.5px; color: var(--ink-3); letter-spacing: .04em; text-transform: uppercase; font-weight: 600; border-bottom: 1px solid var(--border); }
|
||||
table.cmp td { padding: 14px 18px; border-bottom: 1px solid var(--border); font-size: 12.5px; vertical-align: top; }
|
||||
table.cmp tr:last-child td { border-bottom: 0; }
|
||||
table.cmp .row-h { font-weight: 600; color: var(--ink); }
|
||||
table.cmp .stars { color: var(--orange); font-weight: 700; }
|
||||
table.cmp .small { font-size: 11px; color: var(--ink-3); display: block; margin-top: 2px; font-family: 'JetBrains Mono', monospace; letter-spacing: .02em; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
|
||||
<div class="head">
|
||||
<h1>新建商品 · 三版交互方案对比</h1>
|
||||
<div class="sub">
|
||||
<span class="mono">// 流·Studio · AI 生成模式</span>
|
||||
<span>·</span>
|
||||
<span>三个独立 HTML,选定方案后再合并到 <a href="../products.html" style="color:var(--orange);">products.html</a></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ctx-box">
|
||||
<h3>需求背景</h3>
|
||||
<p>商家可能<strong>没有现成的商品图</strong>。需要在原有"上传图片"的基础上,新增一种「AI 生成」模式:商家上传一张随手拍的原图,AI 生成 4 张满意的头图(可重跑),选 1 张;然后选 AI 模特模板,生成 4 张模特上身参考图(可重跑),勾选满意的。</p>
|
||||
<div class="flow-line">
|
||||
[ 上传原图 + 信息 ] <span class="arrow">→</span> [ AI 生成头图 · 4 选 1 ] <span class="arrow">→</span> [ 选模特 + 生成上身图 · 4 选 N ] <span class="arrow">→</span> [ 预览 · 创建 ]
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="versions">
|
||||
|
||||
<!-- ===== 方案 A ===== -->
|
||||
<a class="ver-card" href="mockup-A.html">
|
||||
<div class="ver-preview">
|
||||
<div class="mock">
|
||||
<div class="mock-A-top"><span></span><span></span><span></span><span></span></div>
|
||||
<div class="mock-A-body">
|
||||
<div class="sel"></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="mock-A-foot"><span></span><span class="primary"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ver-info">
|
||||
<span class="badge">[ A · WIZARD ]</span>
|
||||
<h2>分步向导</h2>
|
||||
<p class="tagline">全屏 4 步,顶部 stepper,底部固定工具栏。每步只关注一件事,前进/后退清晰。</p>
|
||||
<ul>
|
||||
<li>跟「新建项目向导」一脉相承,商家熟悉</li>
|
||||
<li>每步沉浸式,不被其他信息干扰</li>
|
||||
<li>4 张候选图大网格 + 居中显示</li>
|
||||
</ul>
|
||||
<div class="pros">
|
||||
<strong>// PROS</strong>
|
||||
最经典最不容易迷路。新手友好,学习成本最低。
|
||||
</div>
|
||||
<div class="cons">
|
||||
<strong>// CONS</strong>
|
||||
不能轻松看到"前面已经选了什么",回头改要点上一步。
|
||||
</div>
|
||||
<div class="cta"><span class="btn btn-primary">查看 Demo →</span></div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<!-- ===== 方案 B ===== -->
|
||||
<a class="ver-card" href="mockup-B.html">
|
||||
<div class="ver-preview">
|
||||
<div class="mock">
|
||||
<div class="mock-B-top"><div class="bar"><span></span></div></div>
|
||||
<div class="mock-B-rows">
|
||||
<div class="mock-B-row done"><span class="num">✓</span><span class="lbl"></span></div>
|
||||
<div class="mock-B-row active"><span class="num"></span><span class="lbl"></span></div>
|
||||
<div class="mock-B-row"><span class="num"></span><span class="lbl"></span></div>
|
||||
<div class="mock-B-row"><span class="num"></span><span class="lbl"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ver-info">
|
||||
<span class="badge">[ B · ACCORDION ]</span>
|
||||
<h2>单页折叠流</h2>
|
||||
<p class="tagline">右侧抽屉,4 步从上到下流式排列。已完成的折叠成"摘要 + 编辑"按钮,当前步展开。</p>
|
||||
<ul>
|
||||
<li>能看到完整流程上下文</li>
|
||||
<li>顶部模式切换:[我有商品图 / AI 生成] 一目了然</li>
|
||||
<li>已选过的随时可以回去改,不丢失</li>
|
||||
</ul>
|
||||
<div class="pros">
|
||||
<strong>// PROS</strong>
|
||||
最完整,适合反复对比和回溯。能跟原有"我有图"模式天然兼容。
|
||||
</div>
|
||||
<div class="cons">
|
||||
<strong>// CONS</strong>
|
||||
页面信息密度略高,初次接触可能有"信息过载"感。
|
||||
</div>
|
||||
<div class="cta"><span class="btn btn-primary">查看 Demo →</span></div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<!-- ===== 方案 C ===== -->
|
||||
<a class="ver-card" href="mockup-C.html">
|
||||
<div class="ver-preview">
|
||||
<div class="mock">
|
||||
<div class="mock-C-top"><div class="ti"></div></div>
|
||||
<div class="mock-C-body">
|
||||
<div class="mock-C-side">
|
||||
<div></div><div class="act"></div><div></div><div></div>
|
||||
</div>
|
||||
<div class="mock-C-canvas">
|
||||
<div class="sel"></div><div></div>
|
||||
<div></div><div></div>
|
||||
</div>
|
||||
<div class="mock-C-controls">
|
||||
<div></div><div></div><div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ver-info">
|
||||
<span class="badge">[ C · WORKBENCH ]</span>
|
||||
<h2>双栏工作台</h2>
|
||||
<p class="tagline">全屏覆盖。左侧步骤导航 + 已选素材,中央大预览图(超大网格),右侧操作面板 + 重新生成参数。</p>
|
||||
<ul>
|
||||
<li>视觉空间最大,选图体验最爽</li>
|
||||
<li>右侧可调"背景风格 / 氛围"等参数后再重跑</li>
|
||||
<li>左侧实时显示已选素材缩略图</li>
|
||||
</ul>
|
||||
<div class="pros">
|
||||
<strong>// PROS</strong>
|
||||
专业感最强,选图最清晰。参考 Pebblely / Booth AI 的成熟方案。
|
||||
</div>
|
||||
<div class="cons">
|
||||
<strong>// CONS</strong>
|
||||
覆盖整个屏幕,跟原有抽屉式新建商品形态差异大。学习成本略高。
|
||||
</div>
|
||||
<div class="cta"><span class="btn btn-primary">查看 Demo →</span></div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="compare-table">
|
||||
<h3>横向对比</h3>
|
||||
<table class="cmp">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 22%;">维度</th>
|
||||
<th>A · 分步向导</th>
|
||||
<th>B · 单页折叠流</th>
|
||||
<th>C · 双栏工作台</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="row-h">傻瓜程度</td>
|
||||
<td><span class="stars">★★★★★</span><span class="small">最简单 · 一次只看一件事</span></td>
|
||||
<td><span class="stars">★★★★</span><span class="small">略复杂 · 但全程可见</span></td>
|
||||
<td><span class="stars">★★★</span><span class="small">需要适应工作台布局</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="row-h">选图视觉空间</td>
|
||||
<td><span class="stars">★★★★</span><span class="small">大,但有页面边距</span></td>
|
||||
<td><span class="stars">★★★</span><span class="small">中等,抽屉宽度限制</span></td>
|
||||
<td><span class="stars">★★★★★</span><span class="small">最大 · 参考 Pebblely</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="row-h">回头修改</td>
|
||||
<td><span class="stars">★★★</span><span class="small">点上一步 / 顶部 stepper</span></td>
|
||||
<td><span class="stars">★★★★★</span><span class="small">点已完成的"编辑"即可</span></td>
|
||||
<td><span class="stars">★★★★</span><span class="small">点左侧 step 切换</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="row-h">"我有图 / AI 生成"双模式融合</td>
|
||||
<td>需要在第 1 步加分支选择</td>
|
||||
<td><strong>顶部就有切换</strong>,无缝</td>
|
||||
<td>需要在顶部或左侧加切换</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="row-h">改原 products.html 的成本</td>
|
||||
<td>中 · 替换抽屉 → 全屏向导</td>
|
||||
<td><strong>低 · 抽屉宽度加大,内部改</strong></td>
|
||||
<td>高 · 完全替换交互形态</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="row-h">参考产品</td>
|
||||
<td>稿定 AI 商品图 · 万相实验室</td>
|
||||
<td>Notion 引导 · Linear 流程</td>
|
||||
<td>Pebblely · Booth AI · 即梦</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 36px; padding: 18px 22px; background: var(--orange-tint); border: 1px solid var(--orange-soft); position: relative;">
|
||||
<div style="font-family:'JetBrains Mono',monospace; font-size:10.5px; color:var(--orange); letter-spacing:.04em; margin-bottom:6px;">// MY RECOMMENDATION</div>
|
||||
<p style="font-size:13px; color:var(--ink); line-height:1.7;">
|
||||
<strong>建议优先选 B(单页折叠流)</strong> ——
|
||||
用户说优先「最简单傻瓜」,但 A 的弱点是「我有图 / AI 生成」两条路要分支处理,流程会割裂;
|
||||
B 在顶部直接放 [我有商品图 / AI 生成] 模式切换,**两种模式共用一套抽屉框架**,改起来也最省事。
|
||||
C 视觉最爽但跟现有抽屉式新建商品差距太大,**留作 V1.5 升级方向**。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- ============= 第二轮:C 方案的"模特挑选"细化 ============= -->
|
||||
<div style="margin-top:48px; padding-bottom:24px; border-bottom:1px solid var(--border); position:relative;">
|
||||
<div style="font-family:'JetBrains Mono',monospace; font-size:10.5px; color:var(--ink-3); letter-spacing:.08em; margin-bottom:8px;">// ROUND 2 · MODEL PICKER REFINEMENT</div>
|
||||
<h2 style="font-size:22px; font-weight:700; letter-spacing:-.012em;">C 方案 · 模特挑选交互细化</h2>
|
||||
<p style="font-size:13px; color:var(--ink-2); margin-top:8px; line-height:1.6;">
|
||||
用户已选 C 方案。模特库规模 <strong>50+</strong> ,需要更重的展示空间(立绘网格 + 悬浮三视图 + 多筛选 + 多选)。
|
||||
下面两版对比:把"选模特"独立成一个 step,还是放在原 Step 3 内部用子 Tab 切换。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="versions" style="margin-top:24px; grid-template-columns: repeat(2, 1fr);">
|
||||
|
||||
<!-- ===== Step 1 ===== -->
|
||||
<a class="ver-card" href="mockup-C-step1.html">
|
||||
<div class="ver-preview">
|
||||
<div class="mock">
|
||||
<div class="mock-C-top"><div class="ti"></div></div>
|
||||
<div class="mock-C-body">
|
||||
<div class="mock-C-side">
|
||||
<div></div><div></div><div class="act"></div><div></div><div></div>
|
||||
</div>
|
||||
<div class="mock-C-canvas" style="grid-template-columns:repeat(3,1fr); grid-template-rows:repeat(2,1fr);">
|
||||
<div class="sel"></div><div></div><div></div>
|
||||
<div></div><div class="sel"></div><div></div>
|
||||
</div>
|
||||
<div class="mock-C-controls">
|
||||
<div></div><div style="height:24px;"></div><div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ver-info">
|
||||
<span class="badge">[ C-STEP1 · 5 STEPS ]</span>
|
||||
<h2>方案 1 · 独立 Step</h2>
|
||||
<p class="tagline">把「选模特」独立成第 3 步,流程从 4 步变 5 步。模特库占满整个 canvas,有完整筛选空间。</p>
|
||||
<ul>
|
||||
<li>左侧 sidebar 出现 NEW 标记,5 步清晰可见</li>
|
||||
<li>顶部搜索 + 7-8 个 filter chips,多选无压力</li>
|
||||
<li>50+ 模特滚动加载,适合大型素材库</li>
|
||||
</ul>
|
||||
<div class="pros">
|
||||
<strong>// PROS</strong>
|
||||
每步只做一件事,模特库展示空间最大,筛选/多选最从容。适合 50+ 大库。
|
||||
</div>
|
||||
<div class="cons">
|
||||
<strong>// CONS</strong>
|
||||
流程多一步,跟之前敲定的"4 步"轻量节奏冲突。"选模特→看效果"被切成两步,要点下一步才看到结果。
|
||||
</div>
|
||||
<div class="cta"><span class="btn btn-primary">查看 Demo →</span></div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<!-- ===== Step 3 (sub-tab) ===== -->
|
||||
<a class="ver-card" href="mockup-C-step3.html">
|
||||
<div class="ver-preview">
|
||||
<div class="mock">
|
||||
<div class="mock-C-top"><div class="ti"></div></div>
|
||||
<div class="mock-C-body">
|
||||
<div class="mock-C-side">
|
||||
<div></div><div></div><div class="act"></div><div></div>
|
||||
</div>
|
||||
<div style="display:flex; flex-direction:column; padding:0;">
|
||||
<div style="display:flex; gap:0; border-bottom:1px solid var(--border); padding:4px 6px; background:var(--bg-soft);">
|
||||
<div style="height:6px; flex:1; background:var(--orange); margin-right:2px;"></div>
|
||||
<div style="height:6px; flex:1; background:var(--bg-soft); border:1px solid var(--border);"></div>
|
||||
</div>
|
||||
<div class="mock-C-canvas" style="grid-template-columns:repeat(3,1fr); grid-template-rows:repeat(2,1fr); flex:1;">
|
||||
<div class="sel"></div><div></div><div></div>
|
||||
<div></div><div class="sel"></div><div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mock-C-controls">
|
||||
<div></div><div style="height:24px;"></div><div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ver-info">
|
||||
<span class="badge">[ C-STEP3 · 4 STEPS + SUB-TAB ]</span>
|
||||
<h2>方案 3 · 子步骤分屏</h2>
|
||||
<p class="tagline">保持 4 步主流程,但 Step 3 内部分两个子 Tab:① 挑选模特 → ② 生成上身图。在同一个 Step 里递进。</p>
|
||||
<ul>
|
||||
<li>主 sidebar 4 个 step 不变,只在 active step 下展开 2 个子项</li>
|
||||
<li>顶部 canvas 上方的子 Tab 条:① → ② 视觉递进</li>
|
||||
<li>选完模特点"下一步"自动跳子 Tab 并触发生成</li>
|
||||
<li>子 Tab 可来回切换,改模特立刻重新生成</li>
|
||||
</ul>
|
||||
<div class="pros">
|
||||
<strong>// PROS</strong>
|
||||
流程不变多。模特挑选 + 看效果在同一个 Step 内,有"递进"感。改模特 → 看新效果链路最短。
|
||||
</div>
|
||||
<div class="cons">
|
||||
<strong>// CONS</strong>
|
||||
子 Tab 比单 step 略复杂一点。主 Step 3 名字"模特上身图"略含糊(其实包含两件事)。
|
||||
</div>
|
||||
<div class="cta"><span class="btn btn-primary">查看 Demo →</span></div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="compare-table" style="margin-top:36px;">
|
||||
<h3>横向对比 · C 方案模特挑选</h3>
|
||||
<table class="cmp">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 24%;">维度</th>
|
||||
<th>方案 1 · 独立 Step</th>
|
||||
<th>方案 3 · 子步骤分屏</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="row-h">主流程步数</td>
|
||||
<td>5 步</td>
|
||||
<td><strong>4 步(子 Tab 内嵌)</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="row-h">模特库展示空间</td>
|
||||
<td><span class="stars">★★★★★</span><span class="small">整个 canvas 都给模特库</span></td>
|
||||
<td><span class="stars">★★★★★</span><span class="small">同样整个 canvas,只少一条 24 px 子 Tab 条</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="row-h">"选模特 → 看上身图效果"链路</td>
|
||||
<td>选 → 下一步 → 等生成 → 看效果(3 步)</td>
|
||||
<td><strong>选 → 切子 Tab → 看效果(2 步,可反复切换)</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="row-h">改模特(已生成上身图后)</td>
|
||||
<td>"上一步" 回 Step 3 → 改 → 再 "下一步" 回 Step 4</td>
|
||||
<td><strong>点子 Tab ① → 改 → 子 Tab ② 自动重新生成</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="row-h">学习成本</td>
|
||||
<td><span class="stars">★★★★★</span><span class="small">最熟悉 · 跟其他 step 一致</span></td>
|
||||
<td><span class="stars">★★★★</span><span class="small">需要适应"主步骤里有子步骤"的概念</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="row-h">侧边栏复杂度</td>
|
||||
<td>5 个 step,均匀</td>
|
||||
<td>4 个 step + Step 3 下展开 2 个子项(可折叠)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="row-h">参考产品</td>
|
||||
<td>Adobe Express 模板挑选 · 阿里万相</td>
|
||||
<td>Figma 工作区子模式 · Photoshop Workspace · 即梦的 Tab 切换</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 24px; padding: 18px 22px; background: var(--orange-tint); border: 1px solid var(--orange-soft); position: relative;">
|
||||
<div style="font-family:'JetBrains Mono',monospace; font-size:10.5px; color:var(--orange); letter-spacing:.04em; margin-bottom:6px;">// MY RECOMMENDATION FOR ROUND 2</div>
|
||||
<p style="font-size:13px; color:var(--ink); line-height:1.7;">
|
||||
<strong>建议选方案 3(子步骤分屏)</strong> ——
|
||||
模特库展示空间一样大(都是整个 canvas),但方案 3 把"挑模特→看上身图效果"做成可来回切换的子 Tab,**改模特时链路最短**(适合反复试不同模特对比效果);
|
||||
流程数也保持 4 步,跟原 C 节奏一致。
|
||||
方案 1 唯一胜出的场景是"用户根本不想改"的一次性流程,但电商商家选模特通常会反复试。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,471 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>方案 A · 分步向导 · 新建商品(AI 生成)</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="../assets/restraint.css">
|
||||
<style>
|
||||
body { background: var(--bg); }
|
||||
.demo-bar {
|
||||
padding: 16px 24px;
|
||||
background: var(--card);
|
||||
border-bottom: 1px solid var(--border);
|
||||
display: flex; align-items: center; gap: 16px;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
.demo-bar .ti { font-weight: 700; font-size: 15px; }
|
||||
.demo-bar .desc { font-family: 'JetBrains Mono', monospace; font-size: 12px; color: var(--ink-3); }
|
||||
|
||||
/* Wizard - full screen modal */
|
||||
.wiz-shell {
|
||||
background: var(--bg);
|
||||
min-height: calc(100vh - 60px);
|
||||
display: flex; flex-direction: column;
|
||||
position: relative; overflow: hidden;
|
||||
}
|
||||
.wiz-shell .grid-bg {
|
||||
position: absolute; inset: 0; pointer-events: none;
|
||||
background-image:
|
||||
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><g stroke='%23B8B3A4' stroke-width='1' fill='none'><path d='M-5 0 L5 0 M0 -5 L0 5'/><path d='M235 0 L245 0 M240 -5 L240 5'/></g></svg>"),
|
||||
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><g stroke='%23E2DED2' stroke-width='1' fill='none' stroke-dasharray='1.5 4'><path d='M240 0 L240 240'/><path d='M0 240 L240 240'/></g></svg>");
|
||||
background-size: 240px 240px, 240px 240px;
|
||||
mask-image: radial-gradient(ellipse 80% 60% at 50% 30%, #000 30%, transparent 90%);
|
||||
-webkit-mask-image: radial-gradient(ellipse 80% 60% at 50% 30%, #000 30%, transparent 90%);
|
||||
}
|
||||
|
||||
/* Top bar */
|
||||
.wiz-top {
|
||||
position: relative; z-index: 2;
|
||||
padding: 14px 32px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: var(--bg);
|
||||
display: flex; align-items: center; gap: 24px;
|
||||
}
|
||||
.wiz-top .home {
|
||||
display: flex; align-items: center; gap: 8px;
|
||||
color: var(--ink-2);
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
}
|
||||
.wiz-top .home:hover { color: var(--ink); }
|
||||
.wiz-top .ti { font-weight: 700; font-size: 16px; }
|
||||
.wiz-top .ti span { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--ink-3); margin-left: 6px; letter-spacing: .04em; }
|
||||
|
||||
/* Stepper */
|
||||
.wiz-stepper {
|
||||
flex: 1;
|
||||
display: flex; align-items: center; justify-content: center; gap: 0;
|
||||
max-width: 640px; margin: 0 auto;
|
||||
}
|
||||
.ws-step {
|
||||
display: flex; align-items: center; gap: 8px;
|
||||
cursor: pointer; user-select: none;
|
||||
}
|
||||
.ws-step .num {
|
||||
width: 24px; height: 24px;
|
||||
border: 1px solid var(--border);
|
||||
background: var(--card);
|
||||
color: var(--ink-3);
|
||||
font-family: 'JetBrains Mono', monospace; font-size: 11px; font-weight: 700;
|
||||
display: grid; place-items: center;
|
||||
}
|
||||
.ws-step.done .num { background: var(--ink); color: #FFF; border-color: var(--ink); }
|
||||
.ws-step.active .num { background: var(--orange); color: #FFF; border-color: var(--orange); }
|
||||
.ws-step .lbl { font-size: 12.5px; color: var(--ink-3); font-weight: 500; }
|
||||
.ws-step.done .lbl { color: var(--ink-2); }
|
||||
.ws-step.active .lbl { color: var(--ink); font-weight: 600; }
|
||||
.ws-line { width: 60px; height: 1px; background: var(--border); margin: 0 12px; }
|
||||
.ws-line.done { background: var(--ink); }
|
||||
.wiz-top .x {
|
||||
width: 32px; height: 32px;
|
||||
border: 1px solid var(--border);
|
||||
display: grid; place-items: center;
|
||||
cursor: pointer;
|
||||
color: var(--ink-2);
|
||||
}
|
||||
.wiz-top .x:hover { color: var(--orange); border-color: var(--orange); }
|
||||
|
||||
/* Body */
|
||||
.wiz-body {
|
||||
position: relative; z-index: 1;
|
||||
flex: 1;
|
||||
padding: 40px 60px 100px;
|
||||
overflow-y: auto;
|
||||
max-width: 1200px;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.step-h { margin-bottom: 28px; text-align: center; }
|
||||
.step-h h2 { font-size: 24px; font-weight: 700; letter-spacing: -.018em; }
|
||||
.step-h p { font-size: 13px; color: var(--ink-2); margin-top: 8px; }
|
||||
.step-h .mono-tag { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--ink-3); letter-spacing: .04em; margin-top: 8px; display: inline-block; padding: 2px 8px; background: var(--bg-soft); border: 1px solid var(--border-soft); }
|
||||
|
||||
.step-pane { display: none; }
|
||||
.step-pane.active { display: block; animation: fade .2s ease; }
|
||||
@keyframes fade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
|
||||
|
||||
/* Step 1: 商品信息 */
|
||||
.s1-grid { display: grid; grid-template-columns: 380px 1fr; gap: 32px; max-width: 880px; margin: 0 auto; }
|
||||
.upload-big {
|
||||
aspect-ratio: 4/5;
|
||||
background: var(--card);
|
||||
border: 1.5px dashed var(--border);
|
||||
display: grid; place-items: center;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
padding: 24px;
|
||||
color: var(--ink-2);
|
||||
transition: border-color .15s, background .15s;
|
||||
}
|
||||
.upload-big:hover { border-color: var(--orange); background: var(--orange-tint); color: var(--orange); }
|
||||
.upload-big .ic-cam { width: 48px; height: 48px; border: 1px solid currentColor; display: grid; place-items: center; margin: 0 auto 14px; }
|
||||
.upload-big.has-file { border-style: solid; border-color: var(--orange); padding: 0; background: var(--bg-soft); }
|
||||
.upload-big.has-file .placeholder { width: 100%; height: 100%; }
|
||||
.up-hint { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--ink-3); text-align: center; margin-top: 10px; letter-spacing: .02em; }
|
||||
|
||||
/* Step 2: 生成头图 4 选 1 */
|
||||
.gen-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; max-width: 1100px; margin: 0 auto; }
|
||||
.gen-card {
|
||||
aspect-ratio: 1;
|
||||
background: var(--card);
|
||||
border: 1px solid var(--border);
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
transition: border-color .12s;
|
||||
overflow: hidden;
|
||||
}
|
||||
.gen-card:hover { border-color: var(--ink-3); }
|
||||
.gen-card .placeholder { width: 100%; height: 100%; }
|
||||
.gen-card.selected { border: 2px solid var(--orange); }
|
||||
.gen-card.selected::after {
|
||||
content: '✓';
|
||||
position: absolute; top: 8px; right: 8px;
|
||||
width: 24px; height: 24px;
|
||||
background: var(--orange); color: #FFF;
|
||||
display: grid; place-items: center;
|
||||
font-weight: 700; font-size: 13px;
|
||||
}
|
||||
.gen-card .badge {
|
||||
position: absolute; bottom: 8px; left: 8px;
|
||||
font-family: 'JetBrains Mono', monospace; font-size: 10px;
|
||||
background: rgba(255,255,255,.92); color: var(--ink-2);
|
||||
border: 1px solid var(--border);
|
||||
padding: 2px 6px; letter-spacing: .04em;
|
||||
}
|
||||
.regen-bar {
|
||||
display: flex; align-items: center; justify-content: center; gap: 12px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
/* Step 3: 模特 + 上身图 */
|
||||
.s3-grid { max-width: 1100px; margin: 0 auto; }
|
||||
.s3-section { margin-bottom: 32px; }
|
||||
.s3-section h3 { font-size: 14px; font-weight: 600; margin-bottom: 14px; display: flex; align-items: center; gap: 8px; }
|
||||
.s3-section h3 .num-mono { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--ink-3); padding: 1px 6px; background: var(--bg-soft); border: 1px solid var(--border-soft); letter-spacing: .04em; }
|
||||
|
||||
.model-row { display: grid; grid-template-columns: repeat(6, 1fr); gap: 10px; }
|
||||
.model-card {
|
||||
aspect-ratio: 3/4;
|
||||
background: var(--card);
|
||||
border: 1px solid var(--border);
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
.model-card:hover { border-color: var(--ink-3); }
|
||||
.model-card.selected { border: 2px solid var(--orange); }
|
||||
.model-card.selected::after { content: '✓'; position: absolute; top: 6px; right: 6px; width: 20px; height: 20px; background: var(--orange); color: #FFF; display: grid; place-items: center; font-weight: 700; font-size: 11px; }
|
||||
.model-card .lbl-bottom { position: absolute; bottom: 0; left: 0; right: 0; background: rgba(255,255,255,.92); border-top: 1px solid var(--border); padding: 4px 8px; font-size: 10.5px; color: var(--ink-2); font-family: 'JetBrains Mono', monospace; letter-spacing: .02em; }
|
||||
.model-card .placeholder { width: 100%; height: 100%; }
|
||||
|
||||
.gen-grid.multi .gen-card.selected { border: 2px solid var(--orange); }
|
||||
.gen-grid.multi .gen-card.selected::after { content: '✓'; }
|
||||
|
||||
/* Step 4: 确认 */
|
||||
.s4-shell { max-width: 760px; margin: 0 auto; }
|
||||
.preview-box { background: var(--card); border: 1px solid var(--border); padding: 0; margin-bottom: 16px; }
|
||||
.preview-box .ph-stack { display: grid; grid-template-columns: 240px 1fr; gap: 0; }
|
||||
.preview-box .ph-stack > .placeholder { aspect-ratio: 4/5; }
|
||||
.preview-box .info { padding: 24px 28px; }
|
||||
.preview-box .info h3 { font-size: 18px; font-weight: 700; margin-bottom: 4px; }
|
||||
.preview-box .info .meta { font-family: 'JetBrains Mono', monospace; font-size: 11.5px; color: var(--ink-3); margin-bottom: 14px; letter-spacing: .02em; }
|
||||
.preview-box .info dl { font-size: 12.5px; color: var(--ink-2); }
|
||||
.preview-box .info dl > div { display: flex; padding: 6px 0; border-bottom: 1px solid var(--border); }
|
||||
.preview-box .info dl > div:last-child { border-bottom: 0; }
|
||||
.preview-box .info dl dt { width: 80px; color: var(--ink-3); font-family: 'JetBrains Mono', monospace; font-size: 11px; letter-spacing: .04em; }
|
||||
.preview-box .info dl dd { flex: 1; color: var(--ink); }
|
||||
.selected-thumbs { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-top: 12px; }
|
||||
.selected-thumbs .placeholder { aspect-ratio: 1; }
|
||||
|
||||
/* Foot bar */
|
||||
.wiz-foot {
|
||||
position: sticky; bottom: 0; z-index: 5;
|
||||
padding: 14px 32px;
|
||||
background: var(--card);
|
||||
border-top: 1px solid var(--border);
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
}
|
||||
.wiz-foot .info { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--ink-3); letter-spacing: .04em; }
|
||||
.wiz-foot .actions { display: flex; gap: 10px; align-items: center; }
|
||||
|
||||
/* Field overrides */
|
||||
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
|
||||
.bullet-list { list-style: none; padding: 0; }
|
||||
.bullet-list li { display: flex; gap: 8px; align-items: center; padding: 8px 10px; background: var(--bg-soft); border: 1px solid var(--border); margin-bottom: 6px; font-size: 13px; }
|
||||
.bullet-list .num { width: 18px; height: 18px; background: var(--card); border: 1px solid var(--border); font-size: 11px; color: var(--ink-2); display: grid; place-items: center; flex-shrink: 0; font-family: 'JetBrains Mono', monospace; }
|
||||
|
||||
.form-card { background: var(--card); border: 1px solid var(--border); padding: 24px; position: relative; }
|
||||
.form-card::before, .form-card::after { content: '+'; position: absolute; color: var(--ink-3); font-family: 'JetBrains Mono', monospace; font-size: 12px; }
|
||||
.form-card::before { top: -7px; left: -7px; }
|
||||
.form-card::after { bottom: -7px; right: -7px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Demo bar (上面只是说明) -->
|
||||
<div class="demo-bar">
|
||||
<a href="index.html" class="btn btn-ghost btn-sm">← 返回方案对比</a>
|
||||
<span class="ti">方案 A · 分步向导(Stepper Wizard)</span>
|
||||
<span class="desc">// 全屏 4 步,顶部 stepper,底部固定工具栏 · 最经典最不容易迷路</span>
|
||||
</div>
|
||||
|
||||
<!-- Wizard -->
|
||||
<div class="wiz-shell">
|
||||
<div class="grid-bg"></div>
|
||||
|
||||
<header class="wiz-top">
|
||||
<div class="home"><svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6"><path d="M3 8L8 3l5 5M5 7v6h6V7"/></svg> 工作台 / 商品库</div>
|
||||
<div class="ti">新建商品 <span>[ AI 生成模式 ]</span></div>
|
||||
|
||||
<nav class="wiz-stepper">
|
||||
<a class="ws-step done" data-step="1"><div class="num">✓</div><div class="lbl">商品信息</div></a>
|
||||
<span class="ws-line done"></span>
|
||||
<a class="ws-step active" data-step="2"><div class="num">2</div><div class="lbl">生成头图</div></a>
|
||||
<span class="ws-line"></span>
|
||||
<a class="ws-step" data-step="3"><div class="num">3</div><div class="lbl">模特上身</div></a>
|
||||
<span class="ws-line"></span>
|
||||
<a class="ws-step" data-step="4"><div class="num">4</div><div class="lbl">完成创建</div></a>
|
||||
</nav>
|
||||
|
||||
<div class="x" onclick="alert('演示原型 · 关闭按钮')"><svg width="14" height="14" viewBox="0 0 16 16"><path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg></div>
|
||||
</header>
|
||||
|
||||
<div class="wiz-body">
|
||||
|
||||
<!-- ============= STEP 1 · 商品信息 + 上传原图 ============= -->
|
||||
<section class="step-pane" data-pane="1">
|
||||
<div class="step-h">
|
||||
<h2>第 1 步 · 上传你的商品图,填写基础信息</h2>
|
||||
<p>上传一张你自己拍摄的商品图(任何角度都行,我们会用 AI 优化),然后填一下商品的基本信息。</p>
|
||||
<span class="mono-tag">// PHOTO + INFO</span>
|
||||
</div>
|
||||
|
||||
<div class="s1-grid">
|
||||
<div>
|
||||
<div class="upload-big has-file">
|
||||
<div class="placeholder"><span class="ph-frame">补水面膜.jpg<br>1200×1500</span></div>
|
||||
</div>
|
||||
<div class="up-hint">// 已上传 · 点击重新选择 · JPG / PNG · 建议 1000×1000+</div>
|
||||
</div>
|
||||
|
||||
<div class="form-card">
|
||||
<div class="field">
|
||||
<label class="field-label">商品名称<span class="req">*</span></label>
|
||||
<input class="input" value="透真玻尿酸补水面膜">
|
||||
</div>
|
||||
<div class="field-row">
|
||||
<div class="field">
|
||||
<label class="field-label">品类</label>
|
||||
<select class="select"><option>美妆个护</option><option>数码 3C</option><option>食品饮料</option></select>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="field-label">参考价</label>
|
||||
<input class="input" value="¥39.9">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="field-label">核心卖点<span class="req">*</span></label>
|
||||
<ul class="bullet-list">
|
||||
<li><span class="num">1</span> 透明质酸 + B5,敷完不黏不闷</li>
|
||||
<li><span class="num">2</span> 30g 大容量精华液</li>
|
||||
<li><span class="num">+</span> <input class="input" style="height:24px; border:0; padding:0 4px; background:transparent;" placeholder="添加新卖点"></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="field-label">目标人群</label>
|
||||
<input class="input" value="22-32 岁女性、熬夜党、敏感肌">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============= STEP 2 · 生成头图 4 选 1 ============= -->
|
||||
<section class="step-pane active" data-pane="2">
|
||||
<div class="step-h">
|
||||
<h2>第 2 步 · 选一张你最满意的头图</h2>
|
||||
<p>AI 已基于你上传的图生成了 4 张优化后的头图,选 1 张作为商品主图。不满意可以重新生成。</p>
|
||||
<span class="mono-tag">// AI generated · 4 candidates</span>
|
||||
</div>
|
||||
|
||||
<div class="gen-grid" id="head-grid">
|
||||
<div class="gen-card selected" data-id="h1"><div class="placeholder"><span class="ph-frame">候选 A · 白底简约</span></div><span class="badge">A · 1920×1920</span></div>
|
||||
<div class="gen-card" data-id="h2"><div class="placeholder"><span class="ph-frame">候选 B · 木纹背景</span></div><span class="badge">B · 1920×1920</span></div>
|
||||
<div class="gen-card" data-id="h3"><div class="placeholder"><span class="ph-frame">候选 C · 浅米石材</span></div><span class="badge">C · 1920×1920</span></div>
|
||||
<div class="gen-card" data-id="h4"><div class="placeholder"><span class="ph-frame">候选 D · 暖光氛围</span></div><span class="badge">D · 1920×1920</span></div>
|
||||
</div>
|
||||
|
||||
<div class="regen-bar">
|
||||
<button class="btn" onclick="regen('head')">↻ 全部重新生成</button>
|
||||
<span style="font-family:'JetBrains Mono',monospace; font-size:11px; color:var(--ink-3); letter-spacing:.04em;">// ~¥0.20 / 4 张 · 不满意不扣费</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============= STEP 3 · 选模特 + 生成上身图 ============= -->
|
||||
<section class="step-pane" data-pane="3">
|
||||
<div class="step-h">
|
||||
<h2>第 3 步 · 选模特,生成模特上身图</h2>
|
||||
<p>从模板库选一个 AI 模特,我们会让 ta 拿着你刚选的商品图生成 4 张上身参考图,选 1-4 张你想要的。</p>
|
||||
<span class="mono-tag">// MODEL + WEAR</span>
|
||||
</div>
|
||||
|
||||
<div class="s3-grid">
|
||||
<div class="s3-section">
|
||||
<h3>① 选模特 <span class="num-mono">12 个 AI 模板 · 已选 1</span></h3>
|
||||
<div class="model-row">
|
||||
<div class="model-card selected"><div class="placeholder"><span class="ph-frame">林夕 · 25</span></div><div class="lbl-bottom">林夕 · 都市女</div></div>
|
||||
<div class="model-card"><div class="placeholder"><span class="ph-frame">阿楠</span></div><div class="lbl-bottom">阿楠 · 同事女</div></div>
|
||||
<div class="model-card"><div class="placeholder"><span class="ph-frame">小七</span></div><div class="lbl-bottom">小七 · 学生</div></div>
|
||||
<div class="model-card"><div class="placeholder"><span class="ph-frame">王姐</span></div><div class="lbl-bottom">王姐 · 居家</div></div>
|
||||
<div class="model-card"><div class="placeholder"><span class="ph-frame">阿杰</span></div><div class="lbl-bottom">阿杰 · 男</div></div>
|
||||
<div class="model-card"><div class="placeholder"><span class="ph-frame">+ 更多</span></div><div class="lbl-bottom">浏览全部</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="s3-section">
|
||||
<h3>② 选你要的上身图(可多选) <span class="num-mono">已选 2 / 4</span></h3>
|
||||
<div class="gen-grid multi" id="wear-grid">
|
||||
<div class="gen-card selected" data-id="w1"><div class="placeholder"><span class="ph-frame">上身 A · 持物半身</span></div><span class="badge">A</span></div>
|
||||
<div class="gen-card" data-id="w2"><div class="placeholder"><span class="ph-frame">上身 B · 敷面膜中</span></div><span class="badge">B</span></div>
|
||||
<div class="gen-card selected" data-id="w3"><div class="placeholder"><span class="ph-frame">上身 C · 镜前自拍</span></div><span class="badge">C</span></div>
|
||||
<div class="gen-card" data-id="w4"><div class="placeholder"><span class="ph-frame">上身 D · 床边特写</span></div><span class="badge">D</span></div>
|
||||
</div>
|
||||
<div class="regen-bar">
|
||||
<button class="btn" onclick="regen('wear')">↻ 重新生成上身图</button>
|
||||
<span style="font-family:'JetBrains Mono',monospace; font-size:11px; color:var(--ink-3); letter-spacing:.04em;">// ~¥0.40 / 4 张</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============= STEP 4 · 完成 ============= -->
|
||||
<section class="step-pane" data-pane="4">
|
||||
<div class="step-h">
|
||||
<h2>第 4 步 · 确认创建</h2>
|
||||
<p>检查一下信息,确认无误就可以创建商品了。后续在新建项目时,这些素材会自动可用。</p>
|
||||
<span class="mono-tag">// REVIEW + CREATE</span>
|
||||
</div>
|
||||
|
||||
<div class="s4-shell">
|
||||
<div class="preview-box">
|
||||
<div class="ph-stack">
|
||||
<div class="placeholder"><span class="ph-frame">头图 A · 1920×1920</span></div>
|
||||
<div class="info">
|
||||
<h3>透真玻尿酸补水面膜</h3>
|
||||
<div class="meta">// 美妆个护 · ¥39.9 · AI 生成 · 模特: 林夕</div>
|
||||
<dl>
|
||||
<div><dt>卖点</dt><dd>透明质酸 + B5 · 30g 大容量精华</dd></div>
|
||||
<div><dt>人群</dt><dd>22-32 岁女性、熬夜党、敏感肌</dd></div>
|
||||
<div><dt>原图</dt><dd>1 张(已上传)</dd></div>
|
||||
<div><dt>头图</dt><dd>1 张(候选 A · AI 生成)</dd></div>
|
||||
<div><dt>上身图</dt><dd>2 张(候选 A · C · AI 模特林夕)</dd></div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 style="font-size:13px; font-weight:600; margin-bottom:8px; color:var(--ink-2);">已选素材</h3>
|
||||
<div class="selected-thumbs">
|
||||
<div class="placeholder"><span class="ph-frame">原图</span></div>
|
||||
<div class="placeholder"><span class="ph-frame">头图 A</span></div>
|
||||
<div class="placeholder"><span class="ph-frame">上身 A</span></div>
|
||||
<div class="placeholder"><span class="ph-frame">上身 C</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
<footer class="wiz-foot">
|
||||
<span class="info" id="foot-info">// STEP 2 / 4 · 已选 1 张头图</span>
|
||||
<div class="actions">
|
||||
<button class="btn" id="btn-prev">← 上一步</button>
|
||||
<button class="btn btn-primary btn-lg" id="btn-next">下一步 →</button>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let curStep = 2;
|
||||
const TOTAL = 4;
|
||||
const labels = ['', '商品信息', '生成头图', '模特上身', '完成创建'];
|
||||
|
||||
function go(n) {
|
||||
if (n < 1 || n > TOTAL) return;
|
||||
curStep = n;
|
||||
document.querySelectorAll('.step-pane').forEach(p => p.classList.remove('active'));
|
||||
document.querySelector(`[data-pane="${n}"]`).classList.add('active');
|
||||
|
||||
document.querySelectorAll('.ws-step').forEach((s, i) => {
|
||||
s.classList.remove('done', 'active');
|
||||
if (i + 1 < n) s.classList.add('done');
|
||||
if (i + 1 === n) s.classList.add('active');
|
||||
});
|
||||
document.querySelectorAll('.ws-line').forEach((l, i) => {
|
||||
l.classList.toggle('done', i + 1 < n);
|
||||
});
|
||||
|
||||
document.getElementById('btn-prev').style.visibility = n === 1 ? 'hidden' : 'visible';
|
||||
document.getElementById('btn-next').textContent = n === TOTAL ? '✓ 创建商品' : '下一步 →';
|
||||
document.getElementById('foot-info').textContent = `// STEP ${n} / ${TOTAL} · ${labels[n]}`;
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
}
|
||||
|
||||
document.getElementById('btn-prev').onclick = () => go(curStep - 1);
|
||||
document.getElementById('btn-next').onclick = () => {
|
||||
if (curStep === TOTAL) {
|
||||
alert('✓ 商品已创建!\n\n(演示原型,实际会跳回商品库)');
|
||||
return;
|
||||
}
|
||||
go(curStep + 1);
|
||||
};
|
||||
document.querySelectorAll('.ws-step').forEach(s => {
|
||||
s.onclick = () => go(+s.dataset.step);
|
||||
});
|
||||
|
||||
// single select for head
|
||||
document.querySelectorAll('#head-grid .gen-card').forEach(c => {
|
||||
c.onclick = () => {
|
||||
document.querySelectorAll('#head-grid .gen-card').forEach(x => x.classList.remove('selected'));
|
||||
c.classList.add('selected');
|
||||
};
|
||||
});
|
||||
// single select for model
|
||||
document.querySelectorAll('.model-card').forEach(c => {
|
||||
c.onclick = () => {
|
||||
document.querySelectorAll('.model-card').forEach(x => x.classList.remove('selected'));
|
||||
c.classList.add('selected');
|
||||
};
|
||||
});
|
||||
// multi select for wear
|
||||
document.querySelectorAll('#wear-grid .gen-card').forEach(c => {
|
||||
c.onclick = () => c.classList.toggle('selected');
|
||||
});
|
||||
|
||||
function regen(t) {
|
||||
const el = document.querySelector(t === 'head' ? '#head-grid' : '#wear-grid');
|
||||
el.style.opacity = .35;
|
||||
setTimeout(() => { el.style.opacity = 1; }, 700);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,440 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>方案 B · 单页折叠流 · 新建商品(AI 生成)</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="../assets/restraint.css">
|
||||
<style>
|
||||
body { background: var(--bg); }
|
||||
.demo-bar { padding: 16px 24px; background: var(--card); border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 16px; font-family: 'Inter', sans-serif; }
|
||||
.demo-bar .ti { font-weight: 700; font-size: 15px; }
|
||||
.demo-bar .desc { font-family: 'JetBrains Mono', monospace; font-size: 12px; color: var(--ink-3); }
|
||||
|
||||
/* Drawer wrapper - simulating right-side drawer */
|
||||
.drawer-shell {
|
||||
background: var(--card);
|
||||
border-left: 1px solid var(--border);
|
||||
width: 920px; max-width: 100vw;
|
||||
margin-left: auto;
|
||||
min-height: calc(100vh - 60px);
|
||||
display: flex; flex-direction: column;
|
||||
position: relative;
|
||||
}
|
||||
.drawer-shell::before, .drawer-shell::after { content: '+'; position: absolute; color: var(--ink-3); font-family: 'JetBrains Mono', monospace; font-size: 12px; }
|
||||
.drawer-shell::before { top: -7px; left: -7px; }
|
||||
.drawer-shell::after { bottom: -7px; right: -7px; }
|
||||
|
||||
.dr-head {
|
||||
padding: 18px 28px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
display: flex; align-items: center; gap: 14px;
|
||||
}
|
||||
.dr-head h2 { font-size: 17px; font-weight: 700; }
|
||||
.dr-head .mode-pill {
|
||||
font-family: 'JetBrains Mono', monospace; font-size: 10.5px;
|
||||
color: var(--orange); background: var(--orange-tint); border: 1px solid var(--orange-soft);
|
||||
padding: 2px 8px; letter-spacing: .04em;
|
||||
}
|
||||
.dr-head .x { margin-left: auto; width: 28px; height: 28px; display: grid; place-items: center; cursor: pointer; color: var(--ink-2); }
|
||||
.dr-head .x:hover { background: var(--bg-soft); color: var(--ink); }
|
||||
|
||||
/* Mode toggle at top */
|
||||
.mode-toggle {
|
||||
padding: 14px 28px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: var(--bg-soft);
|
||||
}
|
||||
.mode-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
|
||||
.mode-card {
|
||||
padding: 14px 16px;
|
||||
background: var(--card);
|
||||
border: 1px solid var(--border);
|
||||
cursor: pointer;
|
||||
display: flex; align-items: center; gap: 12px;
|
||||
}
|
||||
.mode-card:hover { background: var(--bg); border-color: var(--ink-3); }
|
||||
.mode-card.active { border-color: var(--orange); background: var(--orange-tint); }
|
||||
.mode-card .ic-md { width: 36px; height: 36px; background: var(--card); border: 1px solid var(--border); display: grid; place-items: center; color: var(--orange); flex-shrink: 0; }
|
||||
.mode-card.active .ic-md { background: var(--orange); color: #FFF; border-color: var(--orange); }
|
||||
.mode-card .t { font-size: 13px; font-weight: 600; }
|
||||
.mode-card .d { font-size: 11px; color: var(--ink-3); margin-top: 2px; font-family: 'JetBrains Mono', monospace; letter-spacing: .02em; }
|
||||
|
||||
/* Top progress bar */
|
||||
.progress-strip {
|
||||
padding: 16px 28px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
display: flex; align-items: center; gap: 14px;
|
||||
}
|
||||
.progress-strip .lbl { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--ink-3); letter-spacing: .04em; min-width: 70px; }
|
||||
.progress-strip .bar { flex: 1; height: 4px; background: var(--bg-soft); }
|
||||
.progress-strip .bar > span { display: block; height: 100%; background: var(--orange); transition: width .3s; }
|
||||
.progress-strip .pct { font-family: 'JetBrains Mono', monospace; font-size: 12px; font-weight: 700; color: var(--orange); }
|
||||
|
||||
/* Body - vertical accordion sections */
|
||||
.dr-body { flex: 1; overflow-y: auto; }
|
||||
|
||||
.acc-section {
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
.acc-section:last-child { border-bottom: 0; }
|
||||
|
||||
.acc-head {
|
||||
padding: 18px 28px;
|
||||
display: flex; align-items: center; gap: 14px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
position: relative;
|
||||
}
|
||||
.acc-head:hover { background: var(--bg-soft); }
|
||||
.acc-section.locked .acc-head { cursor: not-allowed; opacity: .55; }
|
||||
.acc-section.locked .acc-head:hover { background: transparent; }
|
||||
.acc-num {
|
||||
width: 26px; height: 26px;
|
||||
border: 1px solid var(--border); background: var(--card);
|
||||
color: var(--ink-3);
|
||||
font-family: 'JetBrains Mono', monospace; font-size: 12px; font-weight: 700;
|
||||
display: grid; place-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.acc-section.done .acc-num { background: var(--ink); color: #FFF; border-color: var(--ink); }
|
||||
.acc-section.active .acc-num { background: var(--orange); color: #FFF; border-color: var(--orange); }
|
||||
.acc-meta { flex: 1; }
|
||||
.acc-meta h3 { font-size: 14px; font-weight: 600; }
|
||||
.acc-meta .sm { font-size: 11.5px; color: var(--ink-3); margin-top: 3px; font-family: 'JetBrains Mono', monospace; letter-spacing: .02em; }
|
||||
.acc-section.done .acc-meta .sm { color: var(--ink-2); font-family: 'Inter', sans-serif; letter-spacing: 0; }
|
||||
.acc-summary {
|
||||
display: none;
|
||||
align-items: center; gap: 8px;
|
||||
padding: 6px 12px;
|
||||
background: var(--green-bg); color: var(--green); border: 1px solid var(--green-bd);
|
||||
font-size: 11.5px; font-weight: 600;
|
||||
}
|
||||
.acc-section.done .acc-summary { display: inline-flex; }
|
||||
.acc-section.done .acc-toggle { display: none; }
|
||||
.acc-toggle {
|
||||
padding: 4px 10px;
|
||||
background: var(--bg-soft); border: 1px solid var(--border);
|
||||
font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--ink-2);
|
||||
cursor: pointer;
|
||||
letter-spacing: .04em;
|
||||
}
|
||||
.acc-section.active .acc-toggle { display: none; }
|
||||
.acc-section.locked .acc-toggle { display: none; }
|
||||
|
||||
.acc-body {
|
||||
padding: 0 28px 28px;
|
||||
display: none;
|
||||
}
|
||||
.acc-section.active .acc-body { display: block; animation: fade .2s ease; }
|
||||
@keyframes fade { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }
|
||||
|
||||
.acc-section.done .acc-body-summary {
|
||||
display: block;
|
||||
padding: 0 28px 16px 68px;
|
||||
}
|
||||
.acc-section:not(.done) .acc-body-summary { display: none; }
|
||||
.acc-body-summary { display: none; }
|
||||
.preview-row { display: flex; gap: 8px; align-items: center; }
|
||||
.preview-row .placeholder { width: 40px; height: 40px; }
|
||||
|
||||
/* Step contents */
|
||||
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
|
||||
.upload-mini {
|
||||
aspect-ratio: 4/5;
|
||||
background: var(--bg-soft);
|
||||
border: 1.5px dashed var(--border);
|
||||
display: grid; place-items: center;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
color: var(--ink-2);
|
||||
}
|
||||
.upload-mini.has-file { border-style: solid; padding: 0; background: var(--bg-soft); border-color: var(--orange); }
|
||||
.upload-mini.has-file .placeholder { width: 100%; height: 100%; }
|
||||
.upload-mini .ic-cam { width: 36px; height: 36px; border: 1px solid currentColor; display: grid; place-items: center; margin: 0 auto 10px; }
|
||||
|
||||
.s1-row { display: grid; grid-template-columns: 200px 1fr; gap: 24px; }
|
||||
|
||||
.gen-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
|
||||
.gen-card { aspect-ratio: 1; background: var(--card); border: 1px solid var(--border); cursor: pointer; position: relative; overflow: hidden; }
|
||||
.gen-card:hover { border-color: var(--ink-3); }
|
||||
.gen-card .placeholder { width: 100%; height: 100%; }
|
||||
.gen-card.selected { border: 2px solid var(--orange); }
|
||||
.gen-card.selected::after {
|
||||
content: '✓'; position: absolute; top: 6px; right: 6px;
|
||||
width: 22px; height: 22px; background: var(--orange); color: #FFF;
|
||||
display: grid; place-items: center; font-weight: 700; font-size: 12px;
|
||||
}
|
||||
.gen-card .badge {
|
||||
position: absolute; bottom: 6px; left: 6px;
|
||||
font-family: 'JetBrains Mono', monospace; font-size: 10px;
|
||||
background: rgba(255,255,255,.95); color: var(--ink-2);
|
||||
border: 1px solid var(--border);
|
||||
padding: 1px 5px; letter-spacing: .04em;
|
||||
}
|
||||
|
||||
.regen-line { display: flex; align-items: center; justify-content: space-between; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--border); }
|
||||
.regen-line .info { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--ink-3); letter-spacing: .04em; }
|
||||
|
||||
.model-row { display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; margin-bottom: 18px; }
|
||||
.model-card { aspect-ratio: 3/4; background: var(--card); border: 1px solid var(--border); cursor: pointer; position: relative; }
|
||||
.model-card:hover { border-color: var(--ink-3); }
|
||||
.model-card.selected { border: 2px solid var(--orange); }
|
||||
.model-card.selected::after { content: '✓'; position: absolute; top: 5px; right: 5px; width: 18px; height: 18px; background: var(--orange); color: #FFF; display: grid; place-items: center; font-weight: 700; font-size: 10px; }
|
||||
.model-card .lbl-bottom { position: absolute; bottom: 0; left: 0; right: 0; background: rgba(255,255,255,.95); padding: 3px 6px; font-size: 10px; color: var(--ink-2); font-family: 'JetBrains Mono', monospace; letter-spacing: .02em; text-align: center; }
|
||||
.model-card .placeholder { width: 100%; height: 100%; }
|
||||
|
||||
.sub-h { display: flex; align-items: center; justify-content: space-between; margin: 14px 0 10px; }
|
||||
.sub-h h4 { font-size: 12.5px; font-weight: 600; color: var(--ink-2); }
|
||||
.sub-h .info { font-family: 'JetBrains Mono', monospace; font-size: 10.5px; color: var(--ink-3); letter-spacing: .04em; }
|
||||
|
||||
.bullet-list { list-style: none; padding: 0; }
|
||||
.bullet-list li { display: flex; gap: 8px; align-items: center; padding: 8px 10px; background: var(--bg-soft); border: 1px solid var(--border); margin-bottom: 6px; font-size: 13px; }
|
||||
.bullet-list .num { width: 18px; height: 18px; background: var(--card); border: 1px solid var(--border); font-size: 11px; color: var(--ink-2); display: grid; place-items: center; flex-shrink: 0; font-family: 'JetBrains Mono', monospace; }
|
||||
|
||||
/* Footer */
|
||||
.dr-foot {
|
||||
padding: 14px 28px;
|
||||
border-top: 1px solid var(--border);
|
||||
background: var(--bg-soft);
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
position: sticky; bottom: 0;
|
||||
}
|
||||
.dr-foot .info { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--ink-3); letter-spacing: .04em; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="demo-bar">
|
||||
<a href="index.html" class="btn btn-ghost btn-sm">← 返回方案对比</a>
|
||||
<span class="ti">方案 B · 单页折叠流(Accordion Flow)</span>
|
||||
<span class="desc">// 全流程在一页,选过的折叠摘要,可随时回去改 · 适合反复对比</span>
|
||||
</div>
|
||||
|
||||
<div class="drawer-shell">
|
||||
|
||||
<header class="dr-head">
|
||||
<h2>新建商品</h2>
|
||||
<span class="mode-pill">[ AI 生成模式 ]</span>
|
||||
<div class="x" onclick="alert('演示原型')"><svg width="14" height="14" viewBox="0 0 16 16"><path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg></div>
|
||||
</header>
|
||||
|
||||
<!-- Mode select at top -->
|
||||
<div class="mode-toggle">
|
||||
<div class="mode-grid">
|
||||
<div class="mode-card">
|
||||
<div class="ic-md"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M17 8l-5-5-5 5M12 3v12"/></svg></div>
|
||||
<div><div class="t">我有商品图</div><div class="d">// upload-only · 直接上传图片</div></div>
|
||||
</div>
|
||||
<div class="mode-card active">
|
||||
<div class="ic-md"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M9.663 17h4.673M12 3v1M3.34 7l.7.7M20.66 7l-.7.7M2 12h1M21 12h1M12 19a7 7 0 100-14 7 7 0 000 14z"/></svg></div>
|
||||
<div><div class="t">AI 帮我生成图</div><div class="d">// 上传 1 张原图,AI 出 4 选 1 + 模特上身</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="progress-strip">
|
||||
<span class="lbl">// PROGRESS</span>
|
||||
<div class="bar"><span style="width:50%" id="bar"></span></div>
|
||||
<span class="pct" id="pct">2 / 4</span>
|
||||
</div>
|
||||
|
||||
<div class="dr-body">
|
||||
|
||||
<!-- ============= 1 · 商品信息 (DONE - collapsed) ============= -->
|
||||
<section class="acc-section done" data-step="1">
|
||||
<div class="acc-head">
|
||||
<div class="acc-num">✓</div>
|
||||
<div class="acc-meta">
|
||||
<h3>商品信息 + 上传原图</h3>
|
||||
<div class="sm">透真玻尿酸补水面膜 · 美妆个护 · ¥39.9 · 已上传 1 张原图</div>
|
||||
</div>
|
||||
<span class="acc-summary">✓ 已完成</span>
|
||||
<button class="acc-toggle">编辑</button>
|
||||
</div>
|
||||
<div class="acc-body-summary">
|
||||
<div class="preview-row">
|
||||
<div class="placeholder"><span class="ph-frame">原图</span></div>
|
||||
<div style="font-size:12px; color:var(--ink-3); font-family:'JetBrains Mono',monospace;">// 已记录 · 点击右侧"编辑"修改</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============= 2 · 生成头图 (ACTIVE) ============= -->
|
||||
<section class="acc-section active" data-step="2">
|
||||
<div class="acc-head">
|
||||
<div class="acc-num">2</div>
|
||||
<div class="acc-meta">
|
||||
<h3>生成头图 · 选 1 张</h3>
|
||||
<div class="sm">// AI 已生成 4 张候选 · 点击你最满意的那张</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="acc-body">
|
||||
<div class="gen-grid" id="head-grid">
|
||||
<div class="gen-card selected" data-id="h1"><div class="placeholder"><span class="ph-frame">候选 A · 白底简约</span></div><span class="badge">A</span></div>
|
||||
<div class="gen-card" data-id="h2"><div class="placeholder"><span class="ph-frame">候选 B · 木纹背景</span></div><span class="badge">B</span></div>
|
||||
<div class="gen-card" data-id="h3"><div class="placeholder"><span class="ph-frame">候选 C · 浅米石材</span></div><span class="badge">C</span></div>
|
||||
<div class="gen-card" data-id="h4"><div class="placeholder"><span class="ph-frame">候选 D · 暖光氛围</span></div><span class="badge">D</span></div>
|
||||
</div>
|
||||
<div class="regen-line">
|
||||
<span class="info">// ~¥0.20 / 4 张 · 不满意不扣费</span>
|
||||
<div class="hstack">
|
||||
<button class="btn btn-sm" onclick="regen('head')">↻ 全部重新生成</button>
|
||||
<button class="btn btn-primary btn-sm" onclick="confirmStep(2)">确认这张 →</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============= 3 · 模特上身 (LOCKED until step 2 done) ============= -->
|
||||
<section class="acc-section locked" data-step="3">
|
||||
<div class="acc-head">
|
||||
<div class="acc-num">3</div>
|
||||
<div class="acc-meta">
|
||||
<h3>选模特 · 生成上身图</h3>
|
||||
<div class="sm">// 完成上一步后开启</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="acc-body">
|
||||
<div class="sub-h">
|
||||
<h4>① 选一个 AI 模特</h4>
|
||||
<span class="info">// 12 个模板 · 1 选</span>
|
||||
</div>
|
||||
<div class="model-row">
|
||||
<div class="model-card selected"><div class="placeholder"><span class="ph-frame">林夕 · 25</span></div><div class="lbl-bottom">林夕</div></div>
|
||||
<div class="model-card"><div class="placeholder"><span class="ph-frame">阿楠</span></div><div class="lbl-bottom">阿楠</div></div>
|
||||
<div class="model-card"><div class="placeholder"><span class="ph-frame">小七</span></div><div class="lbl-bottom">小七</div></div>
|
||||
<div class="model-card"><div class="placeholder"><span class="ph-frame">王姐</span></div><div class="lbl-bottom">王姐</div></div>
|
||||
<div class="model-card"><div class="placeholder"><span class="ph-frame">阿杰</span></div><div class="lbl-bottom">阿杰</div></div>
|
||||
<div class="model-card"><div class="placeholder"><span class="ph-frame">+ 更多</span></div><div class="lbl-bottom">浏览全部</div></div>
|
||||
</div>
|
||||
|
||||
<div class="sub-h">
|
||||
<h4>② 选你要的上身图(可多选)</h4>
|
||||
<span class="info">// 已选 2 / 4</span>
|
||||
</div>
|
||||
<div class="gen-grid" id="wear-grid">
|
||||
<div class="gen-card selected" data-id="w1"><div class="placeholder"><span class="ph-frame">上身 A · 持物半身</span></div><span class="badge">A</span></div>
|
||||
<div class="gen-card" data-id="w2"><div class="placeholder"><span class="ph-frame">上身 B · 敷面膜中</span></div><span class="badge">B</span></div>
|
||||
<div class="gen-card selected" data-id="w3"><div class="placeholder"><span class="ph-frame">上身 C · 镜前自拍</span></div><span class="badge">C</span></div>
|
||||
<div class="gen-card" data-id="w4"><div class="placeholder"><span class="ph-frame">上身 D · 床边特写</span></div><span class="badge">D</span></div>
|
||||
</div>
|
||||
<div class="regen-line">
|
||||
<span class="info">// ~¥0.40 / 4 张</span>
|
||||
<div class="hstack">
|
||||
<button class="btn btn-sm" onclick="regen('wear')">↻ 重新生成上身图</button>
|
||||
<button class="btn btn-primary btn-sm" onclick="confirmStep(3)">下一步 →</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============= 4 · 完成 ============= -->
|
||||
<section class="acc-section locked" data-step="4">
|
||||
<div class="acc-head">
|
||||
<div class="acc-num">4</div>
|
||||
<div class="acc-meta">
|
||||
<h3>预览 · 创建</h3>
|
||||
<div class="sm">// 完成上一步后开启</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="acc-body">
|
||||
<p style="font-size:13px; color:var(--ink-2); margin-bottom:14px;">检查信息无误后,点击下方「创建商品」。</p>
|
||||
<div class="preview-row" style="gap:12px;">
|
||||
<div class="placeholder" style="width:120px; height:150px;"><span class="ph-frame">头图 A</span></div>
|
||||
<div class="placeholder" style="width:120px; height:150px;"><span class="ph-frame">上身 A</span></div>
|
||||
<div class="placeholder" style="width:120px; height:150px;"><span class="ph-frame">上身 C</span></div>
|
||||
</div>
|
||||
<button class="btn btn-primary btn-lg" style="margin-top:18px; width:100%;" onclick="alert('✓ 商品已创建!')">✓ 创建商品</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
<footer class="dr-foot">
|
||||
<span class="info" id="foot">// STEP 2 / 4 · 选头图</span>
|
||||
<div class="hstack">
|
||||
<button class="btn">取消</button>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const TOTAL = 4;
|
||||
let activeStep = 2;
|
||||
|
||||
function refreshUI() {
|
||||
const sections = document.querySelectorAll('.acc-section');
|
||||
sections.forEach((s, i) => {
|
||||
const n = i + 1;
|
||||
s.classList.remove('active', 'locked');
|
||||
if (n < activeStep) s.classList.add('done');
|
||||
else s.classList.remove('done');
|
||||
if (n === activeStep) s.classList.add('active');
|
||||
else if (n > activeStep) s.classList.add('locked');
|
||||
});
|
||||
const pct = Math.round(((activeStep - 1) / TOTAL) * 100);
|
||||
document.getElementById('bar').style.width = pct + '%';
|
||||
document.getElementById('pct').textContent = `${activeStep - 1} / ${TOTAL}`;
|
||||
document.getElementById('foot').textContent = `// STEP ${activeStep} / ${TOTAL}`;
|
||||
}
|
||||
|
||||
function confirmStep(n) {
|
||||
activeStep = n + 1;
|
||||
refreshUI();
|
||||
const next = document.querySelector(`[data-step="${activeStep}"]`);
|
||||
if (next) next.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}
|
||||
|
||||
// Click "编辑" on done sections
|
||||
document.querySelectorAll('.acc-section.done .acc-toggle').forEach(b => {
|
||||
b.onclick = (e) => {
|
||||
e.stopPropagation();
|
||||
const sec = b.closest('.acc-section');
|
||||
const n = +sec.dataset.step;
|
||||
activeStep = n;
|
||||
refreshUI();
|
||||
sec.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
};
|
||||
});
|
||||
|
||||
// Click on done section header to expand
|
||||
document.querySelectorAll('.acc-section.done .acc-head').forEach(h => {
|
||||
h.onclick = () => {
|
||||
const sec = h.closest('.acc-section');
|
||||
const n = +sec.dataset.step;
|
||||
activeStep = n;
|
||||
refreshUI();
|
||||
};
|
||||
});
|
||||
|
||||
// single select for head
|
||||
document.querySelectorAll('#head-grid .gen-card').forEach(c => {
|
||||
c.onclick = () => {
|
||||
document.querySelectorAll('#head-grid .gen-card').forEach(x => x.classList.remove('selected'));
|
||||
c.classList.add('selected');
|
||||
};
|
||||
});
|
||||
// single select for model
|
||||
document.querySelectorAll('.model-card').forEach(c => {
|
||||
c.onclick = () => {
|
||||
document.querySelectorAll('.model-card').forEach(x => x.classList.remove('selected'));
|
||||
c.classList.add('selected');
|
||||
};
|
||||
});
|
||||
// multi select for wear
|
||||
document.querySelectorAll('#wear-grid .gen-card').forEach(c => {
|
||||
c.onclick = () => c.classList.toggle('selected');
|
||||
});
|
||||
|
||||
function regen(t) {
|
||||
const el = document.querySelector(t === 'head' ? '#head-grid' : '#wear-grid');
|
||||
el.style.opacity = .35;
|
||||
setTimeout(() => { el.style.opacity = 1; }, 700);
|
||||
}
|
||||
|
||||
refreshUI();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,383 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>方案 1 · 独立 Step · 模特挑选 · 流·Studio</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="../assets/restraint.css">
|
||||
<style>
|
||||
body { background: var(--bg); }
|
||||
.demo-bar { padding: 16px 24px; background: var(--card); border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 16px; font-family: 'Inter', sans-serif; }
|
||||
.demo-bar .ti { font-weight: 700; font-size: 15px; }
|
||||
.demo-bar .desc { font-family: 'JetBrains Mono', monospace; font-size: 12px; color: var(--ink-3); }
|
||||
|
||||
/* Workbench - full screen */
|
||||
.wb { height: calc(100vh - 60px); display: grid; grid-template-rows: 56px 1fr; background: var(--bg); }
|
||||
|
||||
/* Top bar */
|
||||
.wb-top { padding: 0 24px; background: var(--card); border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 18px; }
|
||||
.wb-top .ti { font-size: 15px; font-weight: 700; }
|
||||
.wb-top .ti span { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--orange); background: var(--orange-tint); border: 1px solid var(--orange-soft); padding: 2px 6px; margin-left: 8px; letter-spacing: .04em; }
|
||||
.wb-top .meta-line { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--ink-3); letter-spacing: .04em; }
|
||||
.wb-top .right { margin-left: auto; display: flex; align-items: center; gap: 8px; }
|
||||
.wb-top .x { width: 32px; height: 32px; display: grid; place-items: center; cursor: pointer; color: var(--ink-2); border: 1px solid var(--border); }
|
||||
.wb-top .x:hover { color: var(--orange); border-color: var(--orange); }
|
||||
|
||||
/* Main split */
|
||||
.wb-main { display: grid; grid-template-columns: 280px 1fr 360px; min-height: 0; }
|
||||
|
||||
/* Left sidebar - 5 steps */
|
||||
.wb-side { border-right: 1px solid var(--border); background: var(--bg); overflow-y: auto; padding: 18px 0; }
|
||||
.step-item { padding: 14px 20px; display: flex; align-items: flex-start; gap: 12px; cursor: pointer; border-left: 3px solid transparent; position: relative; }
|
||||
.step-item:hover { background: var(--bg-soft); }
|
||||
.step-item.active { background: var(--orange-tint); border-left-color: var(--orange); }
|
||||
.step-item .num { width: 24px; height: 24px; border: 1px solid var(--border); background: var(--card); color: var(--ink-3); font-family: 'JetBrains Mono', monospace; font-size: 11px; font-weight: 700; display: grid; place-items: center; flex-shrink: 0; }
|
||||
.step-item.done .num { background: var(--ink); color: #FFF; border-color: var(--ink); }
|
||||
.step-item.active .num { background: var(--orange); color: #FFF; border-color: var(--orange); }
|
||||
.step-item .info { flex: 1; min-width: 0; }
|
||||
.step-item .ti2 { font-size: 13.5px; font-weight: 600; color: var(--ink-2); }
|
||||
.step-item.active .ti2 { color: var(--ink); }
|
||||
.step-item .sub { font-size: 11px; color: var(--ink-3); margin-top: 3px; font-family: 'JetBrains Mono', monospace; letter-spacing: .02em; }
|
||||
.step-item.done .sub { color: var(--ink-2); font-family: 'Inter', sans-serif; letter-spacing: 0; }
|
||||
.step-item.new { position: relative; }
|
||||
.step-item.new::after { content: 'NEW'; position: absolute; top: 14px; right: 16px; font-family: 'JetBrains Mono', monospace; font-size: 9px; padding: 1px 5px; background: var(--orange); color: #FFF; letter-spacing: .04em; font-weight: 700; }
|
||||
|
||||
.side-divider { height: 1px; background: var(--border); margin: 14px 20px; }
|
||||
.side-section-h { padding: 4px 20px 8px; font-family: 'JetBrains Mono', monospace; font-size: 10.5px; color: var(--ink-3); letter-spacing: .08em; text-transform: uppercase; font-weight: 600; }
|
||||
|
||||
/* Center canvas */
|
||||
.wb-canvas { background: var(--bg); overflow-y: auto; padding: 28px 32px; display: flex; flex-direction: column; min-width: 0; }
|
||||
.canvas-h { margin-bottom: 18px; display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
|
||||
.canvas-h h2 { font-size: 22px; font-weight: 700; letter-spacing: -.012em; }
|
||||
.canvas-h p { font-size: 13px; color: var(--ink-2); margin-top: 4px; }
|
||||
.canvas-h .step-tag { font-family: 'JetBrains Mono', monospace; font-size: 10.5px; color: var(--ink-3); padding: 3px 8px; background: var(--bg-soft); border: 1px solid var(--border-soft); letter-spacing: .04em; flex-shrink: 0; }
|
||||
|
||||
/* Search + filter toolbar */
|
||||
.filter-bar { display: flex; align-items: center; gap: 10px; margin-bottom: 18px; flex-wrap: wrap; }
|
||||
.search-input { position: relative; width: 280px; }
|
||||
.search-input svg { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--ink-3); width: 14px; height: 14px; }
|
||||
.search-input input { padding-left: 32px; height: 30px; font-size: 12.5px; background: var(--card); border: 1px solid var(--border); color: var(--ink); outline: none; width: 100%; }
|
||||
.filter-chip { height: 30px; padding: 0 10px; border: 1px solid var(--border); background: var(--card); font-size: 12px; color: var(--ink-2); display: inline-flex; align-items: center; gap: 4px; cursor: pointer; font-family: inherit; }
|
||||
.filter-chip:hover { background: var(--bg-soft); }
|
||||
.filter-chip.active { border-color: var(--orange); color: var(--orange); background: var(--orange-tint); font-weight: 600; }
|
||||
.filter-chip svg { width: 11px; height: 11px; }
|
||||
.results-meta { margin-left: auto; font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--ink-3); letter-spacing: .04em; }
|
||||
|
||||
/* Model grid */
|
||||
.model-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 12px; }
|
||||
@media (max-width: 1400px) { .model-grid { grid-template-columns: repeat(5, 1fr); } }
|
||||
@media (max-width: 1200px) { .model-grid { grid-template-columns: repeat(4, 1fr); } }
|
||||
|
||||
.model-card {
|
||||
aspect-ratio: 3/4;
|
||||
background: var(--card);
|
||||
border: 1px solid var(--border);
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.model-card:hover { border-color: var(--ink-3); }
|
||||
.model-card.selected { border: 2px solid var(--orange); }
|
||||
.model-card.selected::after {
|
||||
content: '✓'; position: absolute; top: 6px; right: 6px;
|
||||
width: 22px; height: 22px; background: var(--orange); color: #FFF;
|
||||
display: grid; place-items: center; font-weight: 700; font-size: 12px; z-index: 2;
|
||||
}
|
||||
.model-card .placeholder { width: 100%; height: 100%; }
|
||||
.model-card .lbl-bottom {
|
||||
position: absolute; bottom: 0; left: 0; right: 0;
|
||||
background: rgba(255,255,255,.95); border-top: 1px solid var(--border);
|
||||
padding: 6px 8px;
|
||||
display: flex; flex-direction: column; gap: 2px;
|
||||
}
|
||||
.model-card .lbl-bottom .nm { font-size: 12px; font-weight: 600; color: var(--ink); }
|
||||
.model-card .lbl-bottom .tags {
|
||||
font-family: 'JetBrains Mono', monospace; font-size: 9.5px;
|
||||
color: var(--ink-3); letter-spacing: .02em;
|
||||
}
|
||||
.model-card .pose-tag {
|
||||
position: absolute; top: 6px; left: 6px;
|
||||
background: rgba(0,0,0,.55); color: #FFF;
|
||||
font-family: 'JetBrains Mono', monospace; font-size: 9px;
|
||||
padding: 1px 5px; letter-spacing: .04em;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Right controls - hover detail */
|
||||
.wb-controls { border-left: 1px solid var(--border); background: var(--bg); overflow-y: auto; padding: 22px 22px 100px; display: flex; flex-direction: column; position: relative; }
|
||||
.ctrl-section { margin-bottom: 22px; }
|
||||
.ctrl-section h3 { font-family: 'JetBrains Mono', monospace; font-size: 10.5px; color: var(--ink-3); letter-spacing: .08em; text-transform: uppercase; font-weight: 600; margin-bottom: 10px; }
|
||||
|
||||
/* Hover detail card */
|
||||
.hover-detail { background: var(--card); border: 1px solid var(--border); padding: 14px; }
|
||||
.hover-detail .hd-name { font-size: 15px; font-weight: 700; }
|
||||
.hover-detail .hd-tags { display: flex; gap: 4px; flex-wrap: wrap; margin-top: 6px; }
|
||||
.hover-detail .hd-tags span { font-family: 'JetBrains Mono', monospace; font-size: 10px; color: var(--ink-2); background: var(--bg-soft); border: 1px solid var(--border-soft); padding: 1px 5px; letter-spacing: .02em; }
|
||||
.hover-detail .hd-views { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; margin-top: 12px; }
|
||||
.hover-detail .hd-views .placeholder { aspect-ratio: 3/4; }
|
||||
.hover-detail .hd-meta { display: flex; flex-direction: column; gap: 6px; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); font-size: 11.5px; color: var(--ink-2); }
|
||||
.hover-detail .hd-meta div { display: flex; gap: 8px; }
|
||||
.hover-detail .hd-meta .k { font-family: 'JetBrains Mono', monospace; font-size: 10.5px; color: var(--ink-3); width: 56px; letter-spacing: .04em; }
|
||||
|
||||
/* Selected list */
|
||||
.selected-list { display: flex; flex-direction: column; gap: 6px; }
|
||||
.sel-row { display: flex; align-items: center; gap: 8px; padding: 6px 8px; background: var(--card); border: 1px solid var(--border); }
|
||||
.sel-row .placeholder { width: 28px; height: 36px; flex-shrink: 0; }
|
||||
.sel-row .nm { flex: 1; font-size: 12px; font-weight: 600; }
|
||||
.sel-row .x-btn { width: 18px; height: 18px; display: grid; place-items: center; cursor: pointer; color: var(--ink-3); }
|
||||
.sel-row .x-btn:hover { color: var(--red); }
|
||||
.sel-empty { padding: 14px 12px; text-align: center; font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--ink-3); border: 1px dashed var(--border); letter-spacing: .02em; }
|
||||
|
||||
/* Tip */
|
||||
.tip-mini { padding: 10px 12px; background: var(--orange-tint); border: 1px solid var(--orange-soft); font-size: 11.5px; color: var(--ink-2); line-height: 1.5; }
|
||||
.tip-mini strong { color: var(--orange); display: block; font-family: 'JetBrains Mono', monospace; font-size: 10px; letter-spacing: .04em; margin-bottom: 4px; }
|
||||
|
||||
/* Bottom bar */
|
||||
.wb-bottom { position: absolute; left: 0; right: 0; bottom: 0; padding: 14px 22px; background: var(--card); border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: 10px; }
|
||||
.wb-bottom .row1 { display: flex; align-items: center; justify-content: space-between; }
|
||||
.cost-info { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--ink-3); letter-spacing: .04em; }
|
||||
.cost-info .price { color: var(--orange); font-weight: 700; }
|
||||
|
||||
/* Banner: 5-step indicator */
|
||||
.step-count-banner { padding: 8px 14px; background: var(--orange-tint); border: 1px solid var(--orange-soft); margin-bottom: 16px; display: flex; align-items: center; gap: 10px; font-size: 11.5px; color: var(--ink-2); }
|
||||
.step-count-banner .ic { width: 16px; height: 16px; background: var(--orange); color: #FFF; display: grid; place-items: center; font-family: 'JetBrains Mono', monospace; font-size: 10px; font-weight: 700; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="demo-bar">
|
||||
<a href="index.html" class="btn btn-ghost btn-sm">← 返回方案对比</a>
|
||||
<span class="ti">方案 1 · 独立 Step(5 步流程)</span>
|
||||
<span class="desc">// "选模特" 独立成第 3 步,canvas 充分展示模特库 · 适合 50+ 大型素材库</span>
|
||||
</div>
|
||||
|
||||
<div class="wb">
|
||||
<header class="wb-top">
|
||||
<div class="ti">透真玻尿酸补水面膜 <span>[ AI 生成模式 ]</span></div>
|
||||
<div class="meta-line">// 美妆个护 · ¥39.9 · 已选头图 A · WHITE-BG</div>
|
||||
<div class="right">
|
||||
<button class="btn btn-sm">保存草稿</button>
|
||||
<div class="x"><svg width="14" height="14" viewBox="0 0 16 16"><path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg></div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="wb-main">
|
||||
|
||||
<!-- Left: 5 steps -->
|
||||
<aside class="wb-side">
|
||||
<div class="side-section-h">// CREATE FLOW · 5 STEPS</div>
|
||||
<div class="step-item done"><div class="num">✓</div><div class="info"><div class="ti2">商品信息</div><div class="sub">名称、品类、价格、卖点</div></div></div>
|
||||
<div class="step-item done"><div class="num">✓</div><div class="info"><div class="ti2">生成头图</div><div class="sub">已选 1 / 4 · 候选 A</div></div></div>
|
||||
<div class="step-item active new"><div class="num">3</div><div class="info"><div class="ti2">挑选模特</div><div class="sub">// 50+ 模特库 · 单选/多选</div></div></div>
|
||||
<div class="step-item"><div class="num">4</div><div class="info"><div class="ti2">生成上身图</div><div class="sub">// 4 选 N · 多选保留</div></div></div>
|
||||
<div class="step-item"><div class="num">5</div><div class="info"><div class="ti2">完成创建</div><div class="sub">// 预览 · 提交</div></div></div>
|
||||
|
||||
<div class="side-divider"></div>
|
||||
|
||||
<div class="side-section-h">// SELECTED ASSETS</div>
|
||||
<div style="padding: 0 20px;">
|
||||
<div style="font-size:11.5px; color:var(--ink-3); margin-bottom:6px; font-family:'JetBrains Mono',monospace; letter-spacing:.02em;">原图 · 1 张</div>
|
||||
<div class="placeholder" style="width:100%; aspect-ratio: 4/5; margin-bottom:12px;"><span class="ph-frame">补水面膜<br>1200×1500</span></div>
|
||||
<div style="font-size:11.5px; color:var(--ink-3); margin-bottom:6px; font-family:'JetBrains Mono',monospace; letter-spacing:.02em;">头图 · 候选 A</div>
|
||||
<div class="placeholder" style="width:100%; aspect-ratio: 1; margin-bottom:12px;"><span class="ph-frame">A · 白底简约</span></div>
|
||||
<div style="font-size:11.5px; color:var(--ink-3); font-family:'JetBrains Mono',monospace; letter-spacing:.02em;">模特 · 已选 <span style="color:var(--orange); font-weight:700;" id="sel-count-side">2</span> / 50+</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Center canvas: model picker -->
|
||||
<main class="wb-canvas">
|
||||
<div class="canvas-h">
|
||||
<div>
|
||||
<h2>挑选模特</h2>
|
||||
<p>从 AI 模特库选 1 个或多个模特,统一白 T + 白短裤立绘。悬浮看详情和三视图。</p>
|
||||
</div>
|
||||
<span class="step-tag">// STEP 3 / 5 · MODEL SELECT</span>
|
||||
</div>
|
||||
|
||||
<div class="step-count-banner">
|
||||
<span class="ic">i</span>
|
||||
独立成步的好处:筛选 + 搜索 + 多选都有完整空间,适合 50+ 模特库。代价是流程多一步。
|
||||
</div>
|
||||
|
||||
<div class="filter-bar">
|
||||
<div class="search-input">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>
|
||||
<input type="text" placeholder="搜索模特名称、风格…">
|
||||
</div>
|
||||
<button class="filter-chip active">全部 <span style="font-family:'JetBrains Mono',monospace; opacity:.7;">52</span></button>
|
||||
<button class="filter-chip">女性</button>
|
||||
<button class="filter-chip">男性</button>
|
||||
<button class="filter-chip">25-30 岁</button>
|
||||
<button class="filter-chip">都市白领</button>
|
||||
<button class="filter-chip">学生</button>
|
||||
<button class="filter-chip">居家</button>
|
||||
<button class="filter-chip">健身</button>
|
||||
<button class="filter-chip">+ 更多筛选 <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6"><path d="M4 6l4 4 4-4"/></svg></button>
|
||||
<span class="results-meta">// 12 / 52 · 已选 <span id="sel-count" style="color:var(--orange); font-weight:700;">2</span></span>
|
||||
</div>
|
||||
|
||||
<div class="model-grid" id="model-grid">
|
||||
<div class="model-card selected" data-id="m1" onmouseenter="hoverModel('林夕','女 · 25-30','都市白领',['温柔','日常','OL','通勤'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">林夕 · 都市女</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">林夕</div><div class="tags">女 · 25-30 · 都市白领</div></div>
|
||||
</div>
|
||||
<div class="model-card" data-id="m2" onmouseenter="hoverModel('阿楠','女 · 25-30','姐妹/同事',['精致','干练','短发'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">阿楠</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">阿楠</div><div class="tags">女 · 25-30 · 同事</div></div>
|
||||
</div>
|
||||
<div class="model-card selected" data-id="m3" onmouseenter="hoverModel('小七','女 · 18-22','学生/Z世代',['青春','元气','校园'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">小七 · 学生</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">小七</div><div class="tags">女 · 18-22 · 学生</div></div>
|
||||
</div>
|
||||
<div class="model-card" data-id="m4" onmouseenter="hoverModel('王姐','女 · 38-45','妈妈/居家',['亲和','成熟','温暖'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">王姐 · 居家</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">王姐</div><div class="tags">女 · 38-45 · 妈妈</div></div>
|
||||
</div>
|
||||
<div class="model-card" data-id="m5" onmouseenter="hoverModel('阿杰','男 · 28-35','通勤男',['商务','干练','西装'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">阿杰 · 通勤男</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">阿杰</div><div class="tags">男 · 28-35 · 通勤</div></div>
|
||||
</div>
|
||||
<div class="model-card" data-id="m6" onmouseenter="hoverModel('阿强','男 · 22-28','健身男',['阳光','运动','肌肉'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">阿强 · 健身男</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">阿强</div><div class="tags">男 · 22-28 · 健身</div></div>
|
||||
</div>
|
||||
<div class="model-card" data-id="m7" onmouseenter="hoverModel('小苏','女 · 22-26','文艺研究生',['书卷气','静谧','文艺'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">小苏 · 文艺女</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">小苏</div><div class="tags">女 · 22-26 · 文艺</div></div>
|
||||
</div>
|
||||
<div class="model-card" data-id="m8" onmouseenter="hoverModel('文文','女 · 30-38','母亲',['温柔','母性','温暖'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">文文 · 母亲</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">文文</div><div class="tags">女 · 30-38 · 母亲</div></div>
|
||||
</div>
|
||||
<div class="model-card" data-id="m9" onmouseenter="hoverModel('老王','男 · 45-55','大叔',['沉稳','成熟','商务'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">老王 · 大叔</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">老王</div><div class="tags">男 · 45-55 · 大叔</div></div>
|
||||
</div>
|
||||
<div class="model-card" data-id="m10" onmouseenter="hoverModel('萌萌','女 · 18-22','Z世代',['可爱','潮流','二次元'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">萌萌 · Z世代</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">萌萌</div><div class="tags">女 · 18-22 · Z 世代</div></div>
|
||||
</div>
|
||||
<div class="model-card" data-id="m11" onmouseenter="hoverModel('Leo','男 · 30-38','健身教练',['专业','力量','健身房'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">Leo · 教练</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">Leo</div><div class="tags">男 · 30-38 · 教练</div></div>
|
||||
</div>
|
||||
<div class="model-card" data-id="m12" onmouseenter="hoverModel('双人组合','双人 · 25-30','闺蜜',['亲密','日常','搭档'])">
|
||||
<span class="pose-tag">[ 立绘 · 双人 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">闺蜜双人</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">闺蜜组合</div><div class="tags">双人 · 25-30</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 18px; padding: 12px 16px; background: var(--card); border: 1px dashed var(--border); text-align: center; font-family: 'JetBrains Mono', monospace; font-size: 11.5px; color: var(--ink-3); letter-spacing: .02em;">
|
||||
// 还有 40 个模特 · 滚动加载 / 用上方筛选缩小范围
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Right: hover detail + selected list -->
|
||||
<aside class="wb-controls">
|
||||
<div class="ctrl-section">
|
||||
<h3>// 当前悬浮 · DETAIL</h3>
|
||||
<div class="hover-detail" id="hover-detail">
|
||||
<div class="hd-name">林夕</div>
|
||||
<div class="hd-tags">
|
||||
<span>女</span><span>25-30</span><span>都市白领</span><span>温柔</span><span>OL</span><span>通勤</span>
|
||||
</div>
|
||||
<div class="hd-views">
|
||||
<div class="placeholder"><span class="ph-frame">正面</span></div>
|
||||
<div class="placeholder"><span class="ph-frame">侧面</span></div>
|
||||
<div class="placeholder"><span class="ph-frame">背面</span></div>
|
||||
</div>
|
||||
<div class="hd-meta">
|
||||
<div><span class="k">// 服装</span><span>白 T + 白短裤(默认立绘)</span></div>
|
||||
<div><span class="k">// 年龄</span><span>25-30 岁 · 可微调 ±3</span></div>
|
||||
<div><span class="k">// 身材</span><span>普通女 · 165cm / 50kg</span></div>
|
||||
<div><span class="k">// 用过</span><span>4 个项目 · 平均评分 4.5</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ctrl-section">
|
||||
<h3>// 已选模特 · <span style="color:var(--orange); font-weight:700;" id="sel-count-3">2</span> 个</h3>
|
||||
<div class="selected-list" id="selected-list">
|
||||
<div class="sel-row" data-id="m1">
|
||||
<div class="placeholder"><span class="ph-frame">林</span></div>
|
||||
<div class="nm">林夕 · 都市白领</div>
|
||||
<div class="x-btn" title="移除">✕</div>
|
||||
</div>
|
||||
<div class="sel-row" data-id="m3">
|
||||
<div class="placeholder"><span class="ph-frame">七</span></div>
|
||||
<div class="nm">小七 · 学生</div>
|
||||
<div class="x-btn" title="移除">✕</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ctrl-section">
|
||||
<h3>// TIP</h3>
|
||||
<div class="tip-mini">
|
||||
<strong>多选会怎样?</strong>
|
||||
每选一个模特,下一步会为其各自生成 4 张上身图。已选 2 个 = 8 张候选,可多选保留。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wb-bottom">
|
||||
<div class="row1">
|
||||
<span class="cost-info">// 预计 <span class="price">¥0.80</span> / 8 张</span>
|
||||
<span class="cost-info">3 / 5</span>
|
||||
</div>
|
||||
<div class="hstack">
|
||||
<button class="btn" style="flex:1;">← 上一步</button>
|
||||
<button class="btn btn-primary" style="flex:1;">下一步 → 生成上身图</button>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// multi select
|
||||
document.querySelectorAll('.model-card').forEach(c => {
|
||||
c.onclick = () => {
|
||||
c.classList.toggle('selected');
|
||||
updateCount();
|
||||
};
|
||||
});
|
||||
|
||||
function updateCount() {
|
||||
const n = document.querySelectorAll('.model-card.selected').length;
|
||||
document.getElementById('sel-count').textContent = n;
|
||||
document.getElementById('sel-count-3').textContent = n;
|
||||
document.getElementById('sel-count-side').textContent = n;
|
||||
}
|
||||
|
||||
function hoverModel(name, base, role, tags) {
|
||||
const hd = document.getElementById('hover-detail');
|
||||
hd.querySelector('.hd-name').textContent = name;
|
||||
hd.querySelector('.hd-tags').innerHTML = (base.split(' · ')).concat([role]).concat(tags).map(t => `<span>${t}</span>`).join('');
|
||||
}
|
||||
|
||||
document.querySelectorAll('.x-btn').forEach(b => {
|
||||
b.onclick = (e) => {
|
||||
e.stopPropagation();
|
||||
const row = b.closest('.sel-row');
|
||||
const id = row.dataset.id;
|
||||
document.querySelector(`.model-card[data-id="${id}"]`)?.classList.remove('selected');
|
||||
row.remove();
|
||||
updateCount();
|
||||
};
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,530 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>方案 3 · 子步骤分屏 · 模特挑选 · 流·Studio</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="../assets/restraint.css">
|
||||
<style>
|
||||
body { background: var(--bg); }
|
||||
.demo-bar { padding: 16px 24px; background: var(--card); border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 16px; font-family: 'Inter', sans-serif; }
|
||||
.demo-bar .ti { font-weight: 700; font-size: 15px; }
|
||||
.demo-bar .desc { font-family: 'JetBrains Mono', monospace; font-size: 12px; color: var(--ink-3); }
|
||||
|
||||
.wb { height: calc(100vh - 60px); display: grid; grid-template-rows: 56px 1fr; background: var(--bg); }
|
||||
|
||||
.wb-top { padding: 0 24px; background: var(--card); border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 18px; }
|
||||
.wb-top .ti { font-size: 15px; font-weight: 700; }
|
||||
.wb-top .ti span { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--orange); background: var(--orange-tint); border: 1px solid var(--orange-soft); padding: 2px 6px; margin-left: 8px; letter-spacing: .04em; }
|
||||
.wb-top .meta-line { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--ink-3); letter-spacing: .04em; }
|
||||
.wb-top .right { margin-left: auto; display: flex; align-items: center; gap: 8px; }
|
||||
.wb-top .x { width: 32px; height: 32px; display: grid; place-items: center; cursor: pointer; color: var(--ink-2); border: 1px solid var(--border); }
|
||||
.wb-top .x:hover { color: var(--orange); border-color: var(--orange); }
|
||||
|
||||
.wb-main { display: grid; grid-template-columns: 280px 1fr 360px; min-height: 0; }
|
||||
|
||||
/* Sidebar - 4 steps with sub-items */
|
||||
.wb-side { border-right: 1px solid var(--border); background: var(--bg); overflow-y: auto; padding: 18px 0; }
|
||||
.step-item { padding: 14px 20px; display: flex; align-items: flex-start; gap: 12px; cursor: pointer; border-left: 3px solid transparent; position: relative; }
|
||||
.step-item:hover { background: var(--bg-soft); }
|
||||
.step-item.active { background: var(--orange-tint); border-left-color: var(--orange); }
|
||||
.step-item .num { width: 24px; height: 24px; border: 1px solid var(--border); background: var(--card); color: var(--ink-3); font-family: 'JetBrains Mono', monospace; font-size: 11px; font-weight: 700; display: grid; place-items: center; flex-shrink: 0; }
|
||||
.step-item.done .num { background: var(--ink); color: #FFF; border-color: var(--ink); }
|
||||
.step-item.active .num { background: var(--orange); color: #FFF; border-color: var(--orange); }
|
||||
.step-item .info { flex: 1; min-width: 0; }
|
||||
.step-item .ti2 { font-size: 13.5px; font-weight: 600; color: var(--ink-2); }
|
||||
.step-item.active .ti2 { color: var(--ink); }
|
||||
.step-item .sub { font-size: 11px; color: var(--ink-3); margin-top: 3px; font-family: 'JetBrains Mono', monospace; letter-spacing: .02em; }
|
||||
|
||||
/* Sub items under active step */
|
||||
.substep-list { padding: 4px 20px 8px 56px; }
|
||||
.substep-item {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
padding: 7px 10px;
|
||||
cursor: pointer;
|
||||
font-size: 12px; color: var(--ink-3);
|
||||
border-left: 2px solid var(--border);
|
||||
margin-left: -4px;
|
||||
}
|
||||
.substep-item:hover { color: var(--ink-2); border-left-color: var(--ink-3); }
|
||||
.substep-item.active { color: var(--orange); border-left-color: var(--orange); font-weight: 600; }
|
||||
.substep-item.done { color: var(--ink-2); }
|
||||
.substep-item .num-mini {
|
||||
width: 16px; height: 16px;
|
||||
border: 1px solid currentColor;
|
||||
font-family: 'JetBrains Mono', monospace; font-size: 9px; font-weight: 700;
|
||||
display: grid; place-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.substep-item.active .num-mini, .substep-item.done .num-mini { background: currentColor; color: #FFF; }
|
||||
.substep-item.done .num-mini { background: var(--ink); border-color: var(--ink); }
|
||||
|
||||
.side-divider { height: 1px; background: var(--border); margin: 14px 20px; }
|
||||
.side-section-h { padding: 4px 20px 8px; font-family: 'JetBrains Mono', monospace; font-size: 10.5px; color: var(--ink-3); letter-spacing: .08em; text-transform: uppercase; font-weight: 600; }
|
||||
|
||||
/* Center canvas */
|
||||
.wb-canvas { background: var(--bg); overflow-y: auto; padding: 0; display: flex; flex-direction: column; min-width: 0; }
|
||||
|
||||
/* Sub-tab strip on top */
|
||||
.subtab-strip {
|
||||
padding: 0 32px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: var(--card);
|
||||
display: flex; align-items: center; gap: 0;
|
||||
position: sticky; top: 0; z-index: 5;
|
||||
}
|
||||
.subtab {
|
||||
padding: 14px 18px;
|
||||
font-size: 13px; font-weight: 500;
|
||||
color: var(--ink-2);
|
||||
border-bottom: 2px solid transparent;
|
||||
margin-bottom: -1px;
|
||||
cursor: pointer;
|
||||
display: flex; align-items: center; gap: 8px;
|
||||
}
|
||||
.subtab:hover { color: var(--ink); }
|
||||
.subtab.active { color: var(--orange); border-bottom-color: var(--orange); font-weight: 600; }
|
||||
.subtab.disabled { color: var(--ink-3); cursor: not-allowed; opacity: .55; }
|
||||
.subtab .num-circ {
|
||||
width: 20px; height: 20px;
|
||||
border: 1px solid currentColor;
|
||||
border-radius: 50%;
|
||||
font-family: 'JetBrains Mono', monospace; font-size: 10px; font-weight: 700;
|
||||
display: grid; place-items: center;
|
||||
}
|
||||
.subtab.done .num-circ { background: var(--ink); color: #FFF; border-color: var(--ink); }
|
||||
.subtab.active .num-circ { background: var(--orange); color: #FFF; border-color: var(--orange); }
|
||||
.subtab .arrow { color: var(--ink-3); margin: 0 4px; }
|
||||
.subtab-meta { margin-left: auto; font-family: 'JetBrains Mono', monospace; font-size: 10.5px; color: var(--ink-3); letter-spacing: .04em; }
|
||||
|
||||
/* Canvas inner */
|
||||
.canvas-inner { padding: 24px 32px 40px; flex: 1; }
|
||||
.canvas-h { margin-bottom: 18px; display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
|
||||
.canvas-h h2 { font-size: 22px; font-weight: 700; letter-spacing: -.012em; }
|
||||
.canvas-h p { font-size: 13px; color: var(--ink-2); margin-top: 4px; }
|
||||
.canvas-h .step-tag { font-family: 'JetBrains Mono', monospace; font-size: 10.5px; color: var(--ink-3); padding: 3px 8px; background: var(--bg-soft); border: 1px solid var(--border-soft); letter-spacing: .04em; flex-shrink: 0; }
|
||||
|
||||
.filter-bar { display: flex; align-items: center; gap: 10px; margin-bottom: 18px; flex-wrap: wrap; }
|
||||
.search-input { position: relative; width: 280px; }
|
||||
.search-input svg { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--ink-3); width: 14px; height: 14px; }
|
||||
.search-input input { padding-left: 32px; height: 30px; font-size: 12.5px; background: var(--card); border: 1px solid var(--border); color: var(--ink); outline: none; width: 100%; }
|
||||
.filter-chip { height: 30px; padding: 0 10px; border: 1px solid var(--border); background: var(--card); font-size: 12px; color: var(--ink-2); display: inline-flex; align-items: center; gap: 4px; cursor: pointer; font-family: inherit; }
|
||||
.filter-chip:hover { background: var(--bg-soft); }
|
||||
.filter-chip.active { border-color: var(--orange); color: var(--orange); background: var(--orange-tint); font-weight: 600; }
|
||||
.filter-chip svg { width: 11px; height: 11px; }
|
||||
.results-meta { margin-left: auto; font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--ink-3); letter-spacing: .04em; }
|
||||
|
||||
.model-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 12px; }
|
||||
@media (max-width: 1400px) { .model-grid { grid-template-columns: repeat(5, 1fr); } }
|
||||
@media (max-width: 1200px) { .model-grid { grid-template-columns: repeat(4, 1fr); } }
|
||||
|
||||
.model-card { aspect-ratio: 3/4; background: var(--card); border: 1px solid var(--border); cursor: pointer; position: relative; overflow: hidden; }
|
||||
.model-card:hover { border-color: var(--ink-3); }
|
||||
.model-card.selected { border: 2px solid var(--orange); }
|
||||
.model-card.selected::after { content: '✓'; position: absolute; top: 6px; right: 6px; width: 22px; height: 22px; background: var(--orange); color: #FFF; display: grid; place-items: center; font-weight: 700; font-size: 12px; z-index: 2; }
|
||||
.model-card .placeholder { width: 100%; height: 100%; }
|
||||
.model-card .lbl-bottom { position: absolute; bottom: 0; left: 0; right: 0; background: rgba(255,255,255,.95); border-top: 1px solid var(--border); padding: 6px 8px; display: flex; flex-direction: column; gap: 2px; }
|
||||
.model-card .lbl-bottom .nm { font-size: 12px; font-weight: 600; color: var(--ink); }
|
||||
.model-card .lbl-bottom .tags { font-family: 'JetBrains Mono', monospace; font-size: 9.5px; color: var(--ink-3); letter-spacing: .02em; }
|
||||
.model-card .pose-tag { position: absolute; top: 6px; left: 6px; background: rgba(0,0,0,.55); color: #FFF; font-family: 'JetBrains Mono', monospace; font-size: 9px; padding: 1px 5px; letter-spacing: .04em; z-index: 1; }
|
||||
|
||||
/* Wear (sub-tab 2) */
|
||||
.wear-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; max-width: 760px; }
|
||||
.wear-card { aspect-ratio: 1; background: var(--card); border: 1px solid var(--border); cursor: pointer; position: relative; overflow: hidden; }
|
||||
.wear-card:hover { border-color: var(--ink-3); }
|
||||
.wear-card .placeholder { width: 100%; height: 100%; }
|
||||
.wear-card.selected { border: 3px solid var(--orange); }
|
||||
.wear-card.selected::after { content: '✓'; position: absolute; top: 12px; right: 12px; width: 32px; height: 32px; background: var(--orange); color: #FFF; display: grid; place-items: center; font-weight: 700; font-size: 16px; }
|
||||
.wear-card .corner-info { position: absolute; bottom: 12px; left: 12px; background: rgba(255,255,255,.94); border: 1px solid var(--border); padding: 4px 10px; font-family: 'JetBrains Mono', monospace; font-size: 11px; letter-spacing: .04em; color: var(--ink-2); }
|
||||
|
||||
/* Right panel */
|
||||
.wb-controls { border-left: 1px solid var(--border); background: var(--bg); overflow-y: auto; padding: 22px 22px 100px; display: flex; flex-direction: column; position: relative; }
|
||||
.ctrl-section { margin-bottom: 22px; }
|
||||
.ctrl-section h3 { font-family: 'JetBrains Mono', monospace; font-size: 10.5px; color: var(--ink-3); letter-spacing: .08em; text-transform: uppercase; font-weight: 600; margin-bottom: 10px; }
|
||||
|
||||
.hover-detail { background: var(--card); border: 1px solid var(--border); padding: 14px; }
|
||||
.hover-detail .hd-name { font-size: 15px; font-weight: 700; }
|
||||
.hover-detail .hd-tags { display: flex; gap: 4px; flex-wrap: wrap; margin-top: 6px; }
|
||||
.hover-detail .hd-tags span { font-family: 'JetBrains Mono', monospace; font-size: 10px; color: var(--ink-2); background: var(--bg-soft); border: 1px solid var(--border-soft); padding: 1px 5px; letter-spacing: .02em; }
|
||||
.hover-detail .hd-views { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; margin-top: 12px; }
|
||||
.hover-detail .hd-views .placeholder { aspect-ratio: 3/4; }
|
||||
.hover-detail .hd-meta { display: flex; flex-direction: column; gap: 6px; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); font-size: 11.5px; color: var(--ink-2); }
|
||||
.hover-detail .hd-meta div { display: flex; gap: 8px; }
|
||||
.hover-detail .hd-meta .k { font-family: 'JetBrains Mono', monospace; font-size: 10.5px; color: var(--ink-3); width: 56px; letter-spacing: .04em; }
|
||||
|
||||
.selected-list { display: flex; flex-direction: column; gap: 6px; }
|
||||
.sel-row { display: flex; align-items: center; gap: 8px; padding: 6px 8px; background: var(--card); border: 1px solid var(--border); }
|
||||
.sel-row .placeholder { width: 28px; height: 36px; flex-shrink: 0; }
|
||||
.sel-row .nm { flex: 1; font-size: 12px; font-weight: 600; }
|
||||
.sel-row .x-btn { width: 18px; height: 18px; display: grid; place-items: center; cursor: pointer; color: var(--ink-3); }
|
||||
.sel-row .x-btn:hover { color: var(--red); }
|
||||
|
||||
.tip-mini { padding: 10px 12px; background: var(--orange-tint); border: 1px solid var(--orange-soft); font-size: 11.5px; color: var(--ink-2); line-height: 1.5; }
|
||||
.tip-mini strong { color: var(--orange); display: block; font-family: 'JetBrains Mono', monospace; font-size: 10px; letter-spacing: .04em; margin-bottom: 4px; }
|
||||
|
||||
.wb-bottom { position: absolute; left: 0; right: 0; bottom: 0; padding: 14px 22px; background: var(--card); border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: 10px; }
|
||||
.wb-bottom .row1 { display: flex; align-items: center; justify-content: space-between; }
|
||||
.cost-info { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--ink-3); letter-spacing: .04em; }
|
||||
.cost-info .price { color: var(--orange); font-weight: 700; }
|
||||
|
||||
/* Step pane switching */
|
||||
.sub-pane { display: none; }
|
||||
.sub-pane.active { display: block; animation: fade .2s ease; }
|
||||
@keyframes fade { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="demo-bar">
|
||||
<a href="index.html" class="btn btn-ghost btn-sm">← 返回方案对比</a>
|
||||
<span class="ti">方案 3 · 子步骤分屏(4 步主流程,Step 3 内部 2 个子 Tab)</span>
|
||||
<span class="desc">// 顶部子 Tab 切换:挑选模特 → 生成上身图 · 在同一步骤内递进</span>
|
||||
</div>
|
||||
|
||||
<div class="wb">
|
||||
<header class="wb-top">
|
||||
<div class="ti">透真玻尿酸补水面膜 <span>[ AI 生成模式 ]</span></div>
|
||||
<div class="meta-line">// 美妆个护 · ¥39.9 · 已选头图 A · WHITE-BG</div>
|
||||
<div class="right">
|
||||
<button class="btn btn-sm">保存草稿</button>
|
||||
<div class="x"><svg width="14" height="14" viewBox="0 0 16 16"><path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg></div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="wb-main">
|
||||
|
||||
<!-- Left: 4 main steps + sub items under step 3 -->
|
||||
<aside class="wb-side">
|
||||
<div class="side-section-h">// CREATE FLOW · 4 STEPS</div>
|
||||
<div class="step-item done"><div class="num">✓</div><div class="info"><div class="ti2">商品信息</div><div class="sub">名称、品类、价格、卖点</div></div></div>
|
||||
<div class="step-item done"><div class="num">✓</div><div class="info"><div class="ti2">生成头图</div><div class="sub">已选 1 / 4 · 候选 A</div></div></div>
|
||||
<div class="step-item active">
|
||||
<div class="num">3</div>
|
||||
<div class="info"><div class="ti2">模特上身图</div><div class="sub">// 子流程 · ① 挑模特 → ② 生上身</div></div>
|
||||
</div>
|
||||
<div class="substep-list" id="sub-nav">
|
||||
<div class="substep-item active" data-sub="1">
|
||||
<span class="num-mini">①</span>
|
||||
<span>挑选模特</span>
|
||||
<span style="margin-left:auto; font-family:'JetBrains Mono',monospace; font-size:10px; opacity:.7;">2 / 50+</span>
|
||||
</div>
|
||||
<div class="substep-item" data-sub="2">
|
||||
<span class="num-mini">②</span>
|
||||
<span>生成上身图</span>
|
||||
<span style="margin-left:auto; font-family:'JetBrains Mono',monospace; font-size:10px; opacity:.6;">待开始</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-item"><div class="num">4</div><div class="info"><div class="ti2">完成创建</div><div class="sub">// 预览 · 提交</div></div></div>
|
||||
|
||||
<div class="side-divider"></div>
|
||||
|
||||
<div class="side-section-h">// SELECTED ASSETS</div>
|
||||
<div style="padding: 0 20px;">
|
||||
<div style="font-size:11.5px; color:var(--ink-3); margin-bottom:6px; font-family:'JetBrains Mono',monospace; letter-spacing:.02em;">原图 · 1 张</div>
|
||||
<div class="placeholder" style="width:100%; aspect-ratio: 4/5; margin-bottom:12px;"><span class="ph-frame">补水面膜<br>1200×1500</span></div>
|
||||
<div style="font-size:11.5px; color:var(--ink-3); margin-bottom:6px; font-family:'JetBrains Mono',monospace; letter-spacing:.02em;">头图 · 候选 A</div>
|
||||
<div class="placeholder" style="width:100%; aspect-ratio: 1; margin-bottom:12px;"><span class="ph-frame">A · 白底简约</span></div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Center canvas: with sub-tab strip on top -->
|
||||
<main class="wb-canvas">
|
||||
|
||||
<!-- Sub-tab strip -->
|
||||
<div class="subtab-strip">
|
||||
<div class="subtab active" data-sub="1">
|
||||
<span class="num-circ">①</span>
|
||||
挑选模特
|
||||
</div>
|
||||
<span class="arrow" style="color:var(--ink-3); padding: 0 6px;">→</span>
|
||||
<div class="subtab disabled" data-sub="2">
|
||||
<span class="num-circ">②</span>
|
||||
生成上身图
|
||||
</div>
|
||||
<span class="subtab-meta" id="subtab-meta">// SUB-STEP 1 / 2 · 已选模特 <span style="color:var(--orange); font-weight:700;" id="meta-count">2</span></span>
|
||||
</div>
|
||||
|
||||
<div class="canvas-inner">
|
||||
|
||||
<!-- ============= SUB 1 · 挑选模特 ============= -->
|
||||
<section class="sub-pane active" data-pane="1">
|
||||
<div class="canvas-h">
|
||||
<div>
|
||||
<h2>挑选模特 · 子步骤 ①</h2>
|
||||
<p>从 AI 模特库选 1 个或多个,统一白 T + 白短裤立绘。选好后点右下「下一步 → 生成上身图」自动跳到 ②。</p>
|
||||
</div>
|
||||
<span class="step-tag">// STEP 3 / 4 · SUB 1</span>
|
||||
</div>
|
||||
|
||||
<div class="filter-bar">
|
||||
<div class="search-input">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>
|
||||
<input type="text" placeholder="搜索模特名称、风格…">
|
||||
</div>
|
||||
<button class="filter-chip active">全部 <span style="font-family:'JetBrains Mono',monospace; opacity:.7;">52</span></button>
|
||||
<button class="filter-chip">女性</button>
|
||||
<button class="filter-chip">男性</button>
|
||||
<button class="filter-chip">25-30 岁</button>
|
||||
<button class="filter-chip">都市白领</button>
|
||||
<button class="filter-chip">学生</button>
|
||||
<button class="filter-chip">居家</button>
|
||||
<button class="filter-chip">+ 更多筛选 <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6"><path d="M4 6l4 4 4-4"/></svg></button>
|
||||
<span class="results-meta">// 12 / 52 · 已选 <span id="sel-count" style="color:var(--orange); font-weight:700;">2</span></span>
|
||||
</div>
|
||||
|
||||
<div class="model-grid" id="model-grid">
|
||||
<div class="model-card selected" data-id="m1" onmouseenter="hoverModel('林夕','女 · 25-30','都市白领',['温柔','日常','OL','通勤'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">林夕 · 都市女</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">林夕</div><div class="tags">女 · 25-30 · 都市白领</div></div>
|
||||
</div>
|
||||
<div class="model-card" data-id="m2" onmouseenter="hoverModel('阿楠','女 · 25-30','姐妹/同事',['精致','干练','短发'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">阿楠</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">阿楠</div><div class="tags">女 · 25-30 · 同事</div></div>
|
||||
</div>
|
||||
<div class="model-card selected" data-id="m3" onmouseenter="hoverModel('小七','女 · 18-22','学生/Z世代',['青春','元气','校园'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">小七 · 学生</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">小七</div><div class="tags">女 · 18-22 · 学生</div></div>
|
||||
</div>
|
||||
<div class="model-card" data-id="m4" onmouseenter="hoverModel('王姐','女 · 38-45','妈妈/居家',['亲和','成熟','温暖'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">王姐 · 居家</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">王姐</div><div class="tags">女 · 38-45 · 妈妈</div></div>
|
||||
</div>
|
||||
<div class="model-card" data-id="m5" onmouseenter="hoverModel('阿杰','男 · 28-35','通勤男',['商务','干练','西装'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">阿杰 · 通勤男</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">阿杰</div><div class="tags">男 · 28-35 · 通勤</div></div>
|
||||
</div>
|
||||
<div class="model-card" data-id="m6" onmouseenter="hoverModel('阿强','男 · 22-28','健身男',['阳光','运动','肌肉'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">阿强 · 健身男</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">阿强</div><div class="tags">男 · 22-28 · 健身</div></div>
|
||||
</div>
|
||||
<div class="model-card" data-id="m7" onmouseenter="hoverModel('小苏','女 · 22-26','文艺研究生',['书卷气','静谧','文艺'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">小苏 · 文艺女</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">小苏</div><div class="tags">女 · 22-26 · 文艺</div></div>
|
||||
</div>
|
||||
<div class="model-card" data-id="m8" onmouseenter="hoverModel('文文','女 · 30-38','母亲',['温柔','母性','温暖'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">文文 · 母亲</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">文文</div><div class="tags">女 · 30-38 · 母亲</div></div>
|
||||
</div>
|
||||
<div class="model-card" data-id="m9" onmouseenter="hoverModel('老王','男 · 45-55','大叔',['沉稳','成熟','商务'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">老王 · 大叔</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">老王</div><div class="tags">男 · 45-55 · 大叔</div></div>
|
||||
</div>
|
||||
<div class="model-card" data-id="m10" onmouseenter="hoverModel('萌萌','女 · 18-22','Z世代',['可爱','潮流','二次元'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">萌萌 · Z世代</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">萌萌</div><div class="tags">女 · 18-22 · Z 世代</div></div>
|
||||
</div>
|
||||
<div class="model-card" data-id="m11" onmouseenter="hoverModel('Leo','男 · 30-38','健身教练',['专业','力量','健身房'])">
|
||||
<span class="pose-tag">[ 立绘 · 肩上 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">Leo · 教练</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">Leo</div><div class="tags">男 · 30-38 · 教练</div></div>
|
||||
</div>
|
||||
<div class="model-card" data-id="m12" onmouseenter="hoverModel('双人组合','双人 · 25-30','闺蜜',['亲密','日常','搭档'])">
|
||||
<span class="pose-tag">[ 立绘 · 双人 ]</span>
|
||||
<div class="placeholder"><span class="ph-frame">闺蜜双人</span></div>
|
||||
<div class="lbl-bottom"><div class="nm">闺蜜组合</div><div class="tags">双人 · 25-30</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 18px; padding: 12px 16px; background: var(--card); border: 1px dashed var(--border); text-align: center; font-family: 'JetBrains Mono', monospace; font-size: 11.5px; color: var(--ink-3); letter-spacing: .02em;">
|
||||
// 还有 40 个模特 · 滚动加载 / 用上方筛选缩小范围
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============= SUB 2 · 生成上身图 ============= -->
|
||||
<section class="sub-pane" data-pane="2">
|
||||
<div class="canvas-h">
|
||||
<div>
|
||||
<h2>生成上身图 · 子步骤 ②</h2>
|
||||
<p>已为你选的每个模特生成 4 张上身图,可多选保留。可点 ← 回到「① 挑选模特」改人。</p>
|
||||
</div>
|
||||
<span class="step-tag">// STEP 3 / 4 · SUB 2</span>
|
||||
</div>
|
||||
|
||||
<div style="display:flex; align-items:center; gap:8px; margin-bottom:14px; padding:10px 14px; background: var(--card); border: 1px solid var(--border);">
|
||||
<span style="font-family:'JetBrains Mono',monospace; font-size:11px; color:var(--ink-3); letter-spacing:.02em;">// 当前模特:</span>
|
||||
<button class="filter-chip active" style="height: 26px;">林夕 · 都市白领</button>
|
||||
<button class="filter-chip" style="height: 26px;">小七 · 学生</button>
|
||||
<span style="margin-left:auto; font-family:'JetBrains Mono',monospace; font-size:11px; color:var(--ink-3); letter-spacing:.02em;">// 切换模特看不同上身效果</span>
|
||||
</div>
|
||||
|
||||
<div class="wear-grid">
|
||||
<div class="wear-card selected"><div class="placeholder"><span class="ph-frame">上身 A · 持物半身</span></div><span class="corner-info">[ A · 持物半身 ]</span></div>
|
||||
<div class="wear-card"><div class="placeholder"><span class="ph-frame">上身 B · 敷面膜中</span></div><span class="corner-info">[ B · 敷面膜中 ]</span></div>
|
||||
<div class="wear-card selected"><div class="placeholder"><span class="ph-frame">上身 C · 镜前自拍</span></div><span class="corner-info">[ C · 镜前自拍 ]</span></div>
|
||||
<div class="wear-card"><div class="placeholder"><span class="ph-frame">上身 D · 床边特写</span></div><span class="corner-info">[ D · 床边特写 ]</span></div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 18px; display: flex; align-items: center; gap: 12px;">
|
||||
<button class="btn btn-sm">↻ 全部重新生成(¥0.40)</button>
|
||||
<span style="font-family:'JetBrains Mono',monospace; font-size:11px; color:var(--ink-3); letter-spacing:.02em;">// 不满意不扣费 · 已选 2 / 4 张</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Right controls -->
|
||||
<aside class="wb-controls">
|
||||
<div class="ctrl-section">
|
||||
<h3>// 当前悬浮 · DETAIL</h3>
|
||||
<div class="hover-detail" id="hover-detail">
|
||||
<div class="hd-name">林夕</div>
|
||||
<div class="hd-tags">
|
||||
<span>女</span><span>25-30</span><span>都市白领</span><span>温柔</span><span>OL</span><span>通勤</span>
|
||||
</div>
|
||||
<div class="hd-views">
|
||||
<div class="placeholder"><span class="ph-frame">正面</span></div>
|
||||
<div class="placeholder"><span class="ph-frame">侧面</span></div>
|
||||
<div class="placeholder"><span class="ph-frame">背面</span></div>
|
||||
</div>
|
||||
<div class="hd-meta">
|
||||
<div><span class="k">// 服装</span><span>白 T + 白短裤(默认立绘)</span></div>
|
||||
<div><span class="k">// 年龄</span><span>25-30 岁 · 可微调 ±3</span></div>
|
||||
<div><span class="k">// 身材</span><span>普通女 · 165cm / 50kg</span></div>
|
||||
<div><span class="k">// 用过</span><span>4 个项目 · 平均评分 4.5</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ctrl-section">
|
||||
<h3>// 已选模特 · <span style="color:var(--orange); font-weight:700;" id="sel-count-3">2</span> 个</h3>
|
||||
<div class="selected-list" id="selected-list">
|
||||
<div class="sel-row" data-id="m1">
|
||||
<div class="placeholder"><span class="ph-frame">林</span></div>
|
||||
<div class="nm">林夕 · 都市白领</div>
|
||||
<div class="x-btn" title="移除">✕</div>
|
||||
</div>
|
||||
<div class="sel-row" data-id="m3">
|
||||
<div class="placeholder"><span class="ph-frame">七</span></div>
|
||||
<div class="nm">小七 · 学生</div>
|
||||
<div class="x-btn" title="移除">✕</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ctrl-section">
|
||||
<h3>// TIP</h3>
|
||||
<div class="tip-mini">
|
||||
<strong>子步骤的好处</strong>
|
||||
挑模特 → 生上身在同一个 Step 内推进,左侧 sidebar 不变多。Sub Tab 可来回切换不丢已选。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wb-bottom">
|
||||
<div class="row1">
|
||||
<span class="cost-info">// 预计 <span class="price">¥0.80</span> / 8 张</span>
|
||||
<span class="cost-info" id="bottom-meta">SUB 1 / 2</span>
|
||||
</div>
|
||||
<div class="hstack">
|
||||
<button class="btn" style="flex:1;" id="btn-prev-sub">← 上一步</button>
|
||||
<button class="btn btn-primary" style="flex:1;" id="btn-next-sub">下一步 → 生成上身</button>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let curSub = 1;
|
||||
|
||||
function switchSub(n) {
|
||||
curSub = n;
|
||||
document.querySelectorAll('.sub-pane').forEach(p => p.classList.remove('active'));
|
||||
document.querySelector(`[data-pane="${n}"]`).classList.add('active');
|
||||
|
||||
// sub tabs in canvas
|
||||
document.querySelectorAll('.subtab').forEach(t => {
|
||||
t.classList.remove('active', 'done', 'disabled');
|
||||
const tn = +t.dataset.sub;
|
||||
if (tn < n) t.classList.add('done');
|
||||
else if (tn === n) t.classList.add('active');
|
||||
});
|
||||
|
||||
// sub items in sidebar
|
||||
document.querySelectorAll('.substep-item').forEach(t => {
|
||||
t.classList.remove('active', 'done');
|
||||
const tn = +t.dataset.sub;
|
||||
if (tn < n) t.classList.add('done');
|
||||
else if (tn === n) t.classList.add('active');
|
||||
});
|
||||
|
||||
document.getElementById('subtab-meta').innerHTML = n === 1
|
||||
? '// SUB-STEP 1 / 2 · 已选模特 <span style="color:var(--orange); font-weight:700;">2</span>'
|
||||
: '// SUB-STEP 2 / 2 · 上身图 4 选 N';
|
||||
document.getElementById('bottom-meta').textContent = `SUB ${n} / 2`;
|
||||
document.getElementById('btn-next-sub').textContent = n === 1 ? '下一步 → 生成上身' : '下一步 → 完成创建';
|
||||
|
||||
document.querySelector('.wb-canvas').scrollTop = 0;
|
||||
}
|
||||
|
||||
document.querySelectorAll('.subtab').forEach(t => {
|
||||
t.onclick = () => {
|
||||
if (t.classList.contains('disabled')) {
|
||||
const n = +t.dataset.sub;
|
||||
// allow click after step 1 satisfied
|
||||
switchSub(n);
|
||||
} else {
|
||||
switchSub(+t.dataset.sub);
|
||||
}
|
||||
};
|
||||
});
|
||||
document.querySelectorAll('.substep-item').forEach(t => {
|
||||
t.onclick = () => switchSub(+t.dataset.sub);
|
||||
});
|
||||
document.getElementById('btn-next-sub').onclick = () => {
|
||||
if (curSub === 1) switchSub(2);
|
||||
else alert('→ 进入 Step 4 完成创建');
|
||||
};
|
||||
document.getElementById('btn-prev-sub').onclick = () => {
|
||||
if (curSub === 2) switchSub(1);
|
||||
else alert('← 返回 Step 2 头图');
|
||||
};
|
||||
|
||||
// multi select
|
||||
document.querySelectorAll('.model-card').forEach(c => {
|
||||
c.onclick = () => {
|
||||
c.classList.toggle('selected');
|
||||
updateCount();
|
||||
};
|
||||
});
|
||||
function updateCount() {
|
||||
const n = document.querySelectorAll('.model-card.selected').length;
|
||||
document.getElementById('sel-count').textContent = n;
|
||||
document.getElementById('sel-count-3').textContent = n;
|
||||
document.getElementById('meta-count').textContent = n;
|
||||
}
|
||||
function hoverModel(name, base, role, tags) {
|
||||
const hd = document.getElementById('hover-detail');
|
||||
hd.querySelector('.hd-name').textContent = name;
|
||||
hd.querySelector('.hd-tags').innerHTML = (base.split(' · ')).concat([role]).concat(tags).map(t => `<span>${t}</span>`).join('');
|
||||
}
|
||||
|
||||
// wear cards multi select
|
||||
document.querySelectorAll('.wear-card').forEach(c => {
|
||||
c.onclick = () => c.classList.toggle('selected');
|
||||
});
|
||||
|
||||
document.querySelectorAll('.x-btn').forEach(b => {
|
||||
b.onclick = (e) => {
|
||||
e.stopPropagation();
|
||||
const row = b.closest('.sel-row');
|
||||
const id = row.dataset.id;
|
||||
document.querySelector(`.model-card[data-id="${id}"]`)?.classList.remove('selected');
|
||||
row.remove();
|
||||
updateCount();
|
||||
};
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,476 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>方案 C · 双栏工作台 · 新建商品(AI 生成)</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="../assets/restraint.css">
|
||||
<style>
|
||||
body { background: var(--bg); }
|
||||
.demo-bar { padding: 16px 24px; background: var(--card); border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 16px; font-family: 'Inter', sans-serif; }
|
||||
.demo-bar .ti { font-weight: 700; font-size: 15px; }
|
||||
.demo-bar .desc { font-family: 'JetBrains Mono', monospace; font-size: 12px; color: var(--ink-3); }
|
||||
|
||||
/* Workbench - full screen */
|
||||
.wb {
|
||||
height: calc(100vh - 60px);
|
||||
display: grid;
|
||||
grid-template-rows: 56px 1fr;
|
||||
background: var(--bg);
|
||||
}
|
||||
|
||||
/* Top bar */
|
||||
.wb-top {
|
||||
padding: 0 24px;
|
||||
background: var(--card);
|
||||
border-bottom: 1px solid var(--border);
|
||||
display: flex; align-items: center; gap: 18px;
|
||||
}
|
||||
.wb-top .ti { font-size: 15px; font-weight: 700; }
|
||||
.wb-top .ti span { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--orange); background: var(--orange-tint); border: 1px solid var(--orange-soft); padding: 2px 6px; margin-left: 8px; letter-spacing: .04em; }
|
||||
.wb-top .meta-line { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--ink-3); letter-spacing: .04em; }
|
||||
.wb-top .right { margin-left: auto; display: flex; align-items: center; gap: 8px; }
|
||||
.wb-top .x { width: 32px; height: 32px; display: grid; place-items: center; cursor: pointer; color: var(--ink-2); border: 1px solid var(--border); }
|
||||
.wb-top .x:hover { color: var(--orange); border-color: var(--orange); }
|
||||
|
||||
/* Main split */
|
||||
.wb-main { display: grid; grid-template-columns: 280px 1fr 340px; min-height: 0; }
|
||||
|
||||
/* Left sidebar - steps */
|
||||
.wb-side {
|
||||
border-right: 1px solid var(--border);
|
||||
background: var(--bg);
|
||||
overflow-y: auto;
|
||||
padding: 18px 0;
|
||||
}
|
||||
.step-item {
|
||||
padding: 14px 20px;
|
||||
display: flex; align-items: flex-start; gap: 12px;
|
||||
cursor: pointer;
|
||||
border-left: 3px solid transparent;
|
||||
position: relative;
|
||||
}
|
||||
.step-item:hover { background: var(--bg-soft); }
|
||||
.step-item.active { background: var(--orange-tint); border-left-color: var(--orange); }
|
||||
.step-item .num {
|
||||
width: 24px; height: 24px;
|
||||
border: 1px solid var(--border); background: var(--card);
|
||||
color: var(--ink-3);
|
||||
font-family: 'JetBrains Mono', monospace; font-size: 11px; font-weight: 700;
|
||||
display: grid; place-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.step-item.done .num { background: var(--ink); color: #FFF; border-color: var(--ink); }
|
||||
.step-item.active .num { background: var(--orange); color: #FFF; border-color: var(--orange); }
|
||||
.step-item .info { flex: 1; min-width: 0; }
|
||||
.step-item .ti2 { font-size: 13.5px; font-weight: 600; color: var(--ink-2); }
|
||||
.step-item.active .ti2 { color: var(--ink); }
|
||||
.step-item .sub { font-size: 11px; color: var(--ink-3); margin-top: 3px; font-family: 'JetBrains Mono', monospace; letter-spacing: .02em; line-height: 1.5; }
|
||||
.step-item.done .sub { color: var(--ink-2); font-family: 'Inter', sans-serif; letter-spacing: 0; }
|
||||
|
||||
.side-divider { height: 1px; background: var(--border); margin: 14px 20px; }
|
||||
.side-section-h { padding: 4px 20px 8px; font-family: 'JetBrains Mono', monospace; font-size: 10.5px; color: var(--ink-3); letter-spacing: .08em; text-transform: uppercase; font-weight: 600; }
|
||||
|
||||
/* Center canvas - big preview */
|
||||
.wb-canvas {
|
||||
background: var(--bg);
|
||||
overflow-y: auto;
|
||||
padding: 32px;
|
||||
display: flex; flex-direction: column;
|
||||
position: relative;
|
||||
min-width: 0;
|
||||
}
|
||||
.canvas-h {
|
||||
margin-bottom: 24px;
|
||||
display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
|
||||
}
|
||||
.canvas-h h2 { font-size: 22px; font-weight: 700; letter-spacing: -.012em; }
|
||||
.canvas-h p { font-size: 13px; color: var(--ink-2); margin-top: 4px; }
|
||||
.canvas-h .step-tag { font-family: 'JetBrains Mono', monospace; font-size: 10.5px; color: var(--ink-3); padding: 3px 8px; background: var(--bg-soft); border: 1px solid var(--border-soft); letter-spacing: .04em; flex-shrink: 0; }
|
||||
|
||||
/* Center grid - bigger images */
|
||||
.big-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; max-width: 720px; }
|
||||
.big-card {
|
||||
aspect-ratio: 1;
|
||||
background: var(--card);
|
||||
border: 1px solid var(--border);
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.big-card:hover { border-color: var(--ink-3); }
|
||||
.big-card .placeholder { width: 100%; height: 100%; }
|
||||
.big-card.selected { border: 3px solid var(--orange); }
|
||||
.big-card.selected::after {
|
||||
content: '✓'; position: absolute; top: 12px; right: 12px;
|
||||
width: 32px; height: 32px; background: var(--orange); color: #FFF;
|
||||
display: grid; place-items: center; font-weight: 700; font-size: 16px;
|
||||
}
|
||||
.big-card .corner-info {
|
||||
position: absolute; bottom: 12px; left: 12px;
|
||||
background: rgba(255,255,255,.94);
|
||||
border: 1px solid var(--border);
|
||||
padding: 4px 10px;
|
||||
font-family: 'JetBrains Mono', monospace; font-size: 11px;
|
||||
letter-spacing: .04em; color: var(--ink-2);
|
||||
}
|
||||
|
||||
/* Right panel - controls */
|
||||
.wb-controls {
|
||||
border-left: 1px solid var(--border);
|
||||
background: var(--bg);
|
||||
overflow-y: auto;
|
||||
padding: 22px 22px 100px;
|
||||
display: flex; flex-direction: column;
|
||||
position: relative;
|
||||
}
|
||||
.ctrl-section { margin-bottom: 24px; }
|
||||
.ctrl-section h3 {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: 10.5px;
|
||||
color: var(--ink-3);
|
||||
letter-spacing: .08em;
|
||||
text-transform: uppercase;
|
||||
font-weight: 600;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.ctrl-card {
|
||||
background: var(--card);
|
||||
border: 1px solid var(--border);
|
||||
padding: 14px;
|
||||
font-size: 12.5px;
|
||||
color: var(--ink-2);
|
||||
line-height: 1.6;
|
||||
}
|
||||
.ctrl-card strong { color: var(--ink); font-weight: 600; }
|
||||
.selected-mini { display: flex; gap: 6px; margin-top: 8px; }
|
||||
.selected-mini .placeholder { width: 36px; height: 36px; }
|
||||
.selected-mini .placeholder.empty { background: transparent; border: 1px dashed var(--border); }
|
||||
|
||||
/* Model row in controls */
|
||||
.model-row-side { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
|
||||
.model-card-side { aspect-ratio: 3/4; background: var(--card); border: 1px solid var(--border); cursor: pointer; position: relative; }
|
||||
.model-card-side:hover { border-color: var(--ink-3); }
|
||||
.model-card-side.selected { border: 2px solid var(--orange); }
|
||||
.model-card-side.selected::after { content: '✓'; position: absolute; top: 4px; right: 4px; width: 16px; height: 16px; background: var(--orange); color: #FFF; display: grid; place-items: center; font-weight: 700; font-size: 9px; }
|
||||
.model-card-side .placeholder { width: 100%; height: 100%; }
|
||||
.model-card-side .lbl { position: absolute; bottom: 0; left: 0; right: 0; background: rgba(255,255,255,.95); padding: 2px 4px; font-size: 9.5px; color: var(--ink-2); font-family: 'JetBrains Mono', monospace; text-align: center; letter-spacing: .02em; }
|
||||
|
||||
/* Bottom bar */
|
||||
.wb-bottom {
|
||||
position: absolute; left: 0; right: 0; bottom: 0;
|
||||
padding: 14px 22px;
|
||||
background: var(--card);
|
||||
border-top: 1px solid var(--border);
|
||||
display: flex; flex-direction: column; gap: 10px;
|
||||
}
|
||||
.wb-bottom .row1 { display: flex; align-items: center; justify-content: space-between; }
|
||||
.cost-info { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--ink-3); letter-spacing: .04em; }
|
||||
.cost-info .price { color: var(--orange); font-weight: 700; }
|
||||
|
||||
/* Step 1 form (used when step 1 active) */
|
||||
.form-card { background: var(--card); border: 1px solid var(--border); padding: 22px; max-width: 720px; }
|
||||
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
|
||||
.upload-c {
|
||||
aspect-ratio: 4/5;
|
||||
background: var(--card);
|
||||
border: 1.5px dashed var(--border);
|
||||
display: grid; place-items: center;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
color: var(--ink-2);
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
.upload-c.has-file { border-style: solid; padding: 0; border-color: var(--orange); background: var(--bg-soft); }
|
||||
.upload-c.has-file .placeholder { width: 100%; height: 100%; }
|
||||
.upload-c .ic-cam { width: 40px; height: 40px; border: 1px solid currentColor; display: grid; place-items: center; margin: 0 auto 12px; }
|
||||
|
||||
.bullet-list { list-style: none; padding: 0; }
|
||||
.bullet-list li { display: flex; gap: 8px; align-items: center; padding: 8px 10px; background: var(--bg-soft); border: 1px solid var(--border); margin-bottom: 6px; font-size: 13px; }
|
||||
.bullet-list .num { width: 18px; height: 18px; background: var(--card); border: 1px solid var(--border); font-size: 11px; color: var(--ink-2); display: grid; place-items: center; flex-shrink: 0; font-family: 'JetBrains Mono', monospace; }
|
||||
|
||||
/* Tip box */
|
||||
.tip-mini { padding: 10px 12px; background: var(--orange-tint); border: 1px solid var(--orange-soft); font-size: 11.5px; color: var(--ink-2); margin-bottom: 18px; line-height: 1.5; }
|
||||
.tip-mini strong { color: var(--orange); display: block; font-family: 'JetBrains Mono', monospace; font-size: 10px; letter-spacing: .04em; margin-bottom: 4px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="demo-bar">
|
||||
<a href="index.html" class="btn btn-ghost btn-sm">← 返回方案对比</a>
|
||||
<span class="ti">方案 C · 双栏工作台(Canvas + Sidebar)</span>
|
||||
<span class="desc">// 全屏工作台,左侧导航 + 中间大预览 + 右侧操作 · 视觉空间最大</span>
|
||||
</div>
|
||||
|
||||
<div class="wb">
|
||||
|
||||
<!-- Top -->
|
||||
<header class="wb-top">
|
||||
<div class="ti">透真玻尿酸补水面膜 <span>[ AI 生成模式 ]</span></div>
|
||||
<div class="meta-line">// 美妆个护 · ¥39.9 · 已上传原图</div>
|
||||
<div class="right">
|
||||
<button class="btn btn-sm">保存草稿</button>
|
||||
<div class="x" onclick="alert('演示原型')"><svg width="14" height="14" viewBox="0 0 16 16"><path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg></div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="wb-main">
|
||||
|
||||
<!-- Left sidebar -->
|
||||
<aside class="wb-side">
|
||||
<div class="side-section-h">// CREATE FLOW</div>
|
||||
<div class="step-item done" data-step="1">
|
||||
<div class="num">✓</div>
|
||||
<div class="info">
|
||||
<div class="ti2">商品信息</div>
|
||||
<div class="sub">名称、品类、价格、卖点</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-item active" data-step="2">
|
||||
<div class="num">2</div>
|
||||
<div class="info">
|
||||
<div class="ti2">生成头图</div>
|
||||
<div class="sub">// AI 生成 · 4 选 1</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-item" data-step="3">
|
||||
<div class="num">3</div>
|
||||
<div class="info">
|
||||
<div class="ti2">模特上身图</div>
|
||||
<div class="sub">// 选模特 + 4 选 N</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step-item" data-step="4">
|
||||
<div class="num">4</div>
|
||||
<div class="info">
|
||||
<div class="ti2">完成创建</div>
|
||||
<div class="sub">// 预览 · 提交</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="side-divider"></div>
|
||||
|
||||
<div class="side-section-h">// SELECTED ASSETS</div>
|
||||
<div style="padding: 0 20px;">
|
||||
<div style="font-size:11.5px; color:var(--ink-3); margin-bottom:8px; font-family:'JetBrains Mono',monospace; letter-spacing:.02em;">原图 · 1 张</div>
|
||||
<div class="placeholder" style="width:100%; aspect-ratio: 4/5; margin-bottom:14px;"><span class="ph-frame">补水面膜<br>1200×1500</span></div>
|
||||
<div style="font-size:11.5px; color:var(--ink-3); font-family:'JetBrains Mono',monospace; letter-spacing:.02em;">头图 · 待选</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Center canvas (changes per step) -->
|
||||
<main class="wb-canvas" id="canvas">
|
||||
|
||||
<!-- STEP 2 default view: 生成头图 -->
|
||||
<div class="canvas-h">
|
||||
<div>
|
||||
<h2>选一张你最满意的头图</h2>
|
||||
<p>AI 已基于原图生成 4 张候选,点击你想要的那张。可以重新生成。</p>
|
||||
</div>
|
||||
<span class="step-tag">// STEP 2 / 4 · HEAD IMAGES</span>
|
||||
</div>
|
||||
|
||||
<div class="big-grid" id="head-grid">
|
||||
<div class="big-card selected" data-id="h1">
|
||||
<div class="placeholder"><span class="ph-frame">候选 A · 白底简约 · 适合电商详情</span></div>
|
||||
<span class="corner-info">[ A · 1920×1920 · WHITE-BG ]</span>
|
||||
</div>
|
||||
<div class="big-card" data-id="h2">
|
||||
<div class="placeholder"><span class="ph-frame">候选 B · 木纹背景 · 自然温暖</span></div>
|
||||
<span class="corner-info">[ B · 1920×1920 · WOOD ]</span>
|
||||
</div>
|
||||
<div class="big-card" data-id="h3">
|
||||
<div class="placeholder"><span class="ph-frame">候选 C · 浅米石材 · 高级质感</span></div>
|
||||
<span class="corner-info">[ C · 1920×1920 · STONE ]</span>
|
||||
</div>
|
||||
<div class="big-card" data-id="h4">
|
||||
<div class="placeholder"><span class="ph-frame">候选 D · 暖光氛围 · 生活场景</span></div>
|
||||
<span class="corner-info">[ D · 1920×1920 · AMBIENT ]</span>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Right controls -->
|
||||
<aside class="wb-controls">
|
||||
<div class="ctrl-section">
|
||||
<h3>// 当前选中</h3>
|
||||
<div class="ctrl-card">
|
||||
<strong>候选 A · 白底简约</strong>
|
||||
<div style="margin-top:6px; color:var(--ink-3); font-family:'JetBrains Mono',monospace; font-size:11px; letter-spacing:.02em;">1920×1920 · 适合主图</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ctrl-section">
|
||||
<h3>// 重新生成参数</h3>
|
||||
<div class="field" style="margin-bottom:10px;">
|
||||
<label class="field-label" style="font-size:11.5px;">背景风格</label>
|
||||
<select class="select" style="height:32px; font-size:12px;">
|
||||
<option>纯白底(电商主图)</option>
|
||||
<option>木纹/石材</option>
|
||||
<option>居家场景</option>
|
||||
<option>自定义</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field" style="margin-bottom:10px;">
|
||||
<label class="field-label" style="font-size:11.5px;">画面氛围</label>
|
||||
<select class="select" style="height:32px; font-size:12px;">
|
||||
<option>明亮简洁</option>
|
||||
<option>暖光氛围</option>
|
||||
<option>冷调高级</option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="btn" style="width:100%; margin-top:6px;">↻ 用以上参数重新生成</button>
|
||||
</div>
|
||||
|
||||
<div class="ctrl-section">
|
||||
<h3>// 提示</h3>
|
||||
<div class="tip-mini">
|
||||
<strong>不满意不扣费</strong>
|
||||
重新生成 4 张约 ¥0.20。已生成共 4 张,确认后才扣费。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wb-bottom">
|
||||
<div class="row1">
|
||||
<span class="cost-info">// 累计 <span class="price">¥0.20</span></span>
|
||||
<span class="cost-info">2 / 4</span>
|
||||
</div>
|
||||
<div class="hstack">
|
||||
<button class="btn" style="flex:1;">← 上一步</button>
|
||||
<button class="btn btn-primary" style="flex:1;" id="next-btn">下一步 →</button>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// single select for head
|
||||
document.querySelectorAll('#head-grid .big-card').forEach(c => {
|
||||
c.onclick = () => {
|
||||
document.querySelectorAll('#head-grid .big-card').forEach(x => x.classList.remove('selected'));
|
||||
c.classList.add('selected');
|
||||
};
|
||||
});
|
||||
|
||||
// Step navigation
|
||||
document.querySelectorAll('.step-item').forEach(item => {
|
||||
item.onclick = () => {
|
||||
const step = +item.dataset.step;
|
||||
switchStep(step);
|
||||
};
|
||||
});
|
||||
|
||||
document.getElementById('next-btn').onclick = () => {
|
||||
const cur = document.querySelector('.step-item.active');
|
||||
const n = +cur.dataset.step;
|
||||
if (n < 4) switchStep(n + 1);
|
||||
else alert('✓ 商品已创建!');
|
||||
};
|
||||
|
||||
function switchStep(n) {
|
||||
document.querySelectorAll('.step-item').forEach((s, i) => {
|
||||
s.classList.remove('active', 'done');
|
||||
if (i + 1 < n) s.classList.add('done');
|
||||
if (i + 1 === n) s.classList.add('active');
|
||||
});
|
||||
renderCanvas(n);
|
||||
}
|
||||
|
||||
function renderCanvas(n) {
|
||||
const c = document.getElementById('canvas');
|
||||
if (n === 1) {
|
||||
c.innerHTML = `
|
||||
<div class="canvas-h">
|
||||
<div><h2>填写商品信息 · 上传原图</h2><p>上传一张你拍的商品图(任何角度都行,AI 会优化),并填写商品基本信息。</p></div>
|
||||
<span class="step-tag">// STEP 1 / 4 · INFO + UPLOAD</span>
|
||||
</div>
|
||||
<div style="display:grid; grid-template-columns: 280px 1fr; gap:24px; max-width: 920px;">
|
||||
<div>
|
||||
<div class="upload-c has-file"><div class="placeholder"><span class="ph-frame">补水面膜.jpg<br>1200×1500</span></div></div>
|
||||
<div style="font-family:'JetBrains Mono',monospace; font-size:11px; color:var(--ink-3); text-align:center; letter-spacing:.02em;">// 已上传 · 点击重选</div>
|
||||
</div>
|
||||
<div class="form-card">
|
||||
<div class="field"><label class="field-label">商品名称<span class="req">*</span></label><input class="input" value="透真玻尿酸补水面膜"></div>
|
||||
<div class="field-row">
|
||||
<div class="field"><label class="field-label">品类</label><select class="select"><option>美妆个护</option></select></div>
|
||||
<div class="field"><label class="field-label">参考价</label><input class="input" value="¥39.9"></div>
|
||||
</div>
|
||||
<div class="field"><label class="field-label">核心卖点<span class="req">*</span></label>
|
||||
<ul class="bullet-list">
|
||||
<li><span class="num">1</span> 透明质酸 + B5,敷完不黏不闷</li>
|
||||
<li><span class="num">2</span> 30g 大容量精华液</li>
|
||||
<li><span class="num">+</span> <input class="input" style="height:24px; border:0; padding:0 4px; background:transparent;" placeholder="添加新卖点"></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="field"><label class="field-label">目标人群</label><input class="input" value="22-32 岁女性、熬夜党、敏感肌"></div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
} else if (n === 2) {
|
||||
c.innerHTML = `
|
||||
<div class="canvas-h">
|
||||
<div><h2>选一张你最满意的头图</h2><p>AI 已基于原图生成 4 张候选,点击你想要的那张。可以重新生成。</p></div>
|
||||
<span class="step-tag">// STEP 2 / 4 · HEAD IMAGES</span>
|
||||
</div>
|
||||
<div class="big-grid" id="head-grid">
|
||||
<div class="big-card selected" data-id="h1"><div class="placeholder"><span class="ph-frame">候选 A · 白底简约</span></div><span class="corner-info">[ A · 1920×1920 ]</span></div>
|
||||
<div class="big-card" data-id="h2"><div class="placeholder"><span class="ph-frame">候选 B · 木纹背景</span></div><span class="corner-info">[ B · 1920×1920 ]</span></div>
|
||||
<div class="big-card" data-id="h3"><div class="placeholder"><span class="ph-frame">候选 C · 浅米石材</span></div><span class="corner-info">[ C · 1920×1920 ]</span></div>
|
||||
<div class="big-card" data-id="h4"><div class="placeholder"><span class="ph-frame">候选 D · 暖光氛围</span></div><span class="corner-info">[ D · 1920×1920 ]</span></div>
|
||||
</div>
|
||||
`;
|
||||
bindBig('#head-grid');
|
||||
} else if (n === 3) {
|
||||
c.innerHTML = `
|
||||
<div class="canvas-h">
|
||||
<div><h2>选模特,生成上身图</h2><p>选好模特后,AI 会让 ta 持你刚选的商品图生成 4 张参考图,可多选。</p></div>
|
||||
<span class="step-tag">// STEP 3 / 4 · MODEL + WEAR</span>
|
||||
</div>
|
||||
<div class="big-grid" id="wear-grid" style="grid-template-columns: repeat(2,1fr);">
|
||||
<div class="big-card selected" data-id="w1"><div class="placeholder"><span class="ph-frame">上身 A · 持物半身</span></div><span class="corner-info">[ A · 持物半身 ]</span></div>
|
||||
<div class="big-card" data-id="w2"><div class="placeholder"><span class="ph-frame">上身 B · 敷面膜中</span></div><span class="corner-info">[ B · 敷面膜中 ]</span></div>
|
||||
<div class="big-card selected" data-id="w3"><div class="placeholder"><span class="ph-frame">上身 C · 镜前自拍</span></div><span class="corner-info">[ C · 镜前自拍 ]</span></div>
|
||||
<div class="big-card" data-id="w4"><div class="placeholder"><span class="ph-frame">上身 D · 床边特写</span></div><span class="corner-info">[ D · 床边特写 ]</span></div>
|
||||
</div>
|
||||
`;
|
||||
bindMulti('#wear-grid');
|
||||
} else if (n === 4) {
|
||||
c.innerHTML = `
|
||||
<div class="canvas-h">
|
||||
<div><h2>预览 · 创建</h2><p>检查下面的素材和信息无误后,点击右下「创建商品」。</p></div>
|
||||
<span class="step-tag">// STEP 4 / 4 · CONFIRM</span>
|
||||
</div>
|
||||
<div style="background:var(--card); border:1px solid var(--border); padding:32px; max-width: 760px;">
|
||||
<h3 style="font-size:20px; font-weight:700;">透真玻尿酸补水面膜</h3>
|
||||
<div style="font-family:'JetBrains Mono',monospace; font-size:11.5px; color:var(--ink-3); margin-top:4px; letter-spacing:.02em;">// 美妆个护 · ¥39.9 · AI 生成 · 模特: 林夕</div>
|
||||
<div style="display:grid; grid-template-columns: repeat(4,1fr); gap:10px; margin-top:18px;">
|
||||
<div class="placeholder" style="aspect-ratio:1;"><span class="ph-frame">原图</span></div>
|
||||
<div class="placeholder" style="aspect-ratio:1;"><span class="ph-frame">头图 A</span></div>
|
||||
<div class="placeholder" style="aspect-ratio:1;"><span class="ph-frame">上身 A</span></div>
|
||||
<div class="placeholder" style="aspect-ratio:1;"><span class="ph-frame">上身 C</span></div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
function bindBig(sel) {
|
||||
document.querySelectorAll(sel + ' .big-card').forEach(c => {
|
||||
c.onclick = () => {
|
||||
document.querySelectorAll(sel + ' .big-card').forEach(x => x.classList.remove('selected'));
|
||||
c.classList.add('selected');
|
||||
};
|
||||
});
|
||||
}
|
||||
function bindMulti(sel) {
|
||||
document.querySelectorAll(sel + ' .big-card').forEach(c => {
|
||||
c.onclick = () => c.classList.toggle('selected');
|
||||
});
|
||||
}
|
||||
|
||||
bindBig('#head-grid');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user