Files
image-suite-studio/extension/entrypoints/sidepanel/index.html
T
2026-08-16 17:32:43 +08:00

320 lines
14 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>电商套图工作台</title>
<style>
:root {
--bg: #f5f5f5; /* 页面背景(中性灰) */
--card: #ffffff;
--card-soft: #fafafa;
--border: #f0f0f0;
--border-strong: #e0e0e0;
--primary: #8b5cf6; /* 紫(ozon-seller-kit v2 主题色) */
--primary-hover: #7c3aed;
--primary-ring: rgba(139, 92, 246, 0.12);
--green: #52c41a;
--red: #ff4d4f;
--warn-bg: #fffbe6;
--warn-border: #ffe58f;
--warn-text: #8c6d1f;
--text: #262626;
--text-2: #8c8c8c;
}
html, body, #root {
min-width: 860px;
margin: 0;
padding: 0;
}
body {
background: var(--bg);
color: var(--text);
font-family: Arial, 'PingFang SC', 'Microsoft YaHei', sans-serif;
font-size: 14px;
}
* { box-sizing: border-box; }
/* ── 页面骨架 ── */
.page { padding: 16px 18px 22px; }
/* 采集区两列等高:左右卡片拉伸到同一高度 */
.two-col { display: flex; gap: 14px; align-items: stretch; margin-bottom: 14px; }
.two-col .section { flex: 1; min-width: 0; margin-bottom: 0; display: flex; flex-direction: column; }
.two-col .section .section-head { flex-shrink: 0; }
/* 图片列表占满 section 除标题外的剩余高度;min-height:0 是 flex 子项内滚动的关键 */
.img-groups { flex: 1 1 auto; min-height: 0; overflow-y: auto; max-height: 78vh; }
/* 采集图片区:section 自身去掉左右 padding,标题行自持 padding
图片区左侧对齐标题,右侧只留窄缝给滚动条(滚动条贴卡片内缘,图片与滚动条之间有小间距) */
.section-images { padding: 14px 0 !important; }
.section-images .section-head { padding: 0 16px; }
.section-images .img-groups { padding: 2px 8px 0 16px; }
.section-images .empty { margin: 0 16px; }
.divider { border-top: 1px solid var(--border); margin: 12px 0; }
/* ── 顶部 ── */
.topbar {
display: flex; align-items: center; gap: 11px;
padding-bottom: 14px; margin-bottom: 14px;
border-bottom: 1px solid var(--border);
}
.logo {
width: 38px; height: 38px; border-radius: 9px;
background: var(--primary); color: #fff;
display: flex; align-items: center; justify-content: center;
font-size: 19px; font-weight: 700;
}
.topbar h1 { font-size: 17px; margin: 0; font-weight: 700; }
.topbar .sub { font-size: 12px; color: var(--text-2); margin-top: 1px; }
.topbar .spacer { flex: 1; }
.btn {
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
padding: 8px 16px; border-radius: 8px; border: 1px solid var(--border-strong);
font-size: 14px; cursor: pointer; user-select: none;
background: #fff; color: var(--text);
transition: all .15s;
}
.btn:hover { border-color: var(--primary); color: var(--primary); }
.btn-primary {
background: var(--primary); border-color: var(--primary); color: #fff;
font-weight: 600;
}
.btn-primary:hover { background: var(--primary-hover); border-color: var(--primary-hover); color: #fff; }
/* AI 智能规划:深靛紫渐变(智慧/深度感) */
.btn-ai {
background: linear-gradient(135deg, #4338ca 0%, #6d28d9 100%);
border: none; color: #fff; font-weight: 600;
box-shadow: 0 2px 10px rgba(88, 60, 210, 0.35);
}
.btn-ai:hover:not([disabled]) {
background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%);
color: #fff; box-shadow: 0 3px 14px rgba(88, 60, 210, 0.45);
}
/* 三个主操作按钮统一宽度 */
.btn-main { width: 160px; }
/* 「规划并生成」复选框 */
.auto-chk {
display: inline-flex; align-items: center; gap: 5px;
font-size: 12.5px; color: var(--text-2); cursor: pointer; user-select: none;
}
.auto-chk input { accent-color: var(--primary); width: 14px; height: 14px; cursor: pointer; }
.auto-chk:hover { color: var(--text); }
.btn[disabled] { opacity: .5; cursor: not-allowed; }
.btn-sm { padding: 5px 11px; font-size: 12.5px; }
.icon-btn {
width: 34px; height: 34px; border-radius: 8px; border: 1px solid var(--border-strong);
background: #fff; cursor: pointer; color: var(--text-2);
display: inline-flex; align-items: center; justify-content: center;
}
.icon-btn:hover { color: var(--primary); border-color: var(--primary); }
/* ── 编号步骤卡片 ── */
.section {
background: var(--card); border: 1px solid var(--border);
border-radius: 8px; padding: 14px 16px; margin-bottom: 14px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.02);
}
.section-head { display: flex; align-items: baseline; gap: 9px; margin-bottom: 12px; }
.section-no {
font-size: 20px; font-weight: 800; color: var(--primary);
font-variant-numeric: tabular-nums; line-height: 1;
}
.section-title { font-size: 15px; font-weight: 700; }
.section-extra { margin-left: auto; font-size: 12px; color: var(--text-2); }
/* ── 字段 ── */
.field { margin-bottom: 10px; }
.field label { display: block; font-size: 12.5px; color: var(--text-2); margin-bottom: 4px; }
.field input, .field textarea {
width: 100%; padding: 8px 11px; border: 1px solid var(--border-strong);
border-radius: 6px; font-size: 14px; font-family: inherit; line-height: 1.5;
background: var(--card-soft); color: var(--text); outline: none;
transition: border-color .15s, box-shadow .15s;
}
.field input:focus, .field textarea:focus {
border-color: var(--primary);
box-shadow: 0 0 0 3px var(--primary-ring);
background: #fff;
}
.kv-table {
width: 100%; border-collapse: collapse; font-size: 13px;
background: var(--card-soft); border-radius: 6px; overflow: hidden;
}
.kv-table td { padding: 6px 10px; border-bottom: 1px solid var(--border); vertical-align: top; }
.kv-table tr:last-child td { border-bottom: none; }
.kv-table td.k { color: var(--text-2); white-space: nowrap; width: 1%; padding-right: 16px; }
/* ── 药丸选择 ── */
.pills { display: flex; flex-wrap: wrap; gap: 7px; }
.pill {
display: inline-flex; align-items: center; justify-content: center;
padding: 5px 13px; border-radius: 999px; border: 1px solid var(--border-strong);
background: #fff; font-size: 13px; cursor: pointer; color: var(--text-2);
user-select: none; transition: all .15s; line-height: 1.4;
}
.pill:hover { border-color: var(--primary); color: var(--primary); }
.pill.on {
background: var(--primary); border-color: var(--primary); color: #fff; font-weight: 600;
}
/* ── 图片网格 ── */
.group-head { display: flex; align-items: center; gap: 8px; margin: 4px 0 9px; }
.group-head .name { font-size: 13px; font-weight: 600; color: var(--text-2); }
.group-head .count {
font-size: 12px; color: var(--text-2); background: var(--card-soft);
border: 1px solid var(--border); border-radius: 999px; padding: 0 8px;
}
.group-head .mini-check { margin-left: auto; font-size: 12px; color: var(--primary); cursor: pointer; user-select: none; }
.group-head .mini-check:hover { text-decoration: underline; }
.img-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 7px; }
.img-cell {
position: relative; aspect-ratio: 1; border-radius: 6px; overflow: hidden;
border: 2px solid transparent; cursor: zoom-in; background: var(--card-soft);
}
.img-cell img { width: 100%; height: 100%; object-fit: cover; display: block; }
.img-cell.on { border-color: var(--primary); }
.img-cell .tick {
position: absolute; top: 5px; left: 5px; width: 18px; height: 18px;
border-radius: 50%; border: 1.5px solid #fff;
background: rgba(255, 255, 255, 0.55); display: flex; align-items: center; justify-content: center;
color: #fff; font-size: 11px; transition: all .15s; cursor: pointer;
}
.img-cell.on .tick { background: var(--primary); border-color: var(--primary); }
.img-cell .variant {
position: absolute; bottom: 0; left: 0; right: 0;
background: rgba(0, 0, 0, 0.55); color: #fff; font-size: 11px;
padding: 1px 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* ── 生成结果(整行,6 列)── */
.result-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; }
.result-cell { position: relative; border-radius: 6px; overflow: hidden; border: 1px solid var(--border); }
.result-cell img { width: 100%; aspect-ratio: 1; object-fit: cover; display: block; }
.result-cell .cap {
font-size: 11.5px; text-align: center; padding: 3px 0;
background: var(--card-soft); color: var(--text-2);
border-top: 1px solid var(--border); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.result-cell.fail { opacity: .55; }
.result-cell .fail-tag {
position: absolute; top: 5px; right: 5px; font-size: 11px;
background: var(--red); color: #fff; border-radius: 4px; padding: 0 5px;
}
/* ── 目标平台切换条 ── */
.platform-bar {
display: flex; align-items: center; gap: 10px;
background: var(--card); border: 1px solid var(--border);
border-radius: 8px; padding: 10px 16px; margin-bottom: 14px;
}
.platform-label { font-size: 13px; font-weight: 700; }
.platform-spec { margin-left: auto; font-size: 12.5px; color: var(--text-2); }
/* 平台切换:Button.Group 形式,选中态用低饱和灰绿(不抢主题色) */
.seg-group { display: inline-flex; }
.seg-btn {
padding: 7px 20px; font-size: 13.5px; font-family: inherit;
min-width: 120px; text-align: center; /* 选中加粗会让文字变宽,固定宽度消除跳动 */
background: #fff; border: 1px solid var(--border-strong); border-left-width: 0;
color: var(--text-2); cursor: pointer; user-select: none; transition: all .15s;
}
.seg-group .seg-btn:first-child { border-left-width: 1px; border-radius: 8px 0 0 8px; }
.seg-group .seg-btn:last-child { border-radius: 0 8px 8px 0; }
.seg-btn:hover { color: var(--text); background: var(--card-soft); }
.seg-btn.on {
background: #eef0eb; border-color: #c9cec6; color: #3f453c; font-weight: 700;
}
.seg-group .seg-btn.on + .seg-btn { border-left-color: #c9cec6; }
/* 三个平台药丸等宽:选中态加粗会让文字变宽,用固定 min-width 消除抖动 */
.platform-bar .pill { min-width: 108px; text-align: center; }
/* ── 图片放大预览(画廊)── */
.lightbox {
position: fixed; inset: 0; z-index: 1000;
background: rgba(0, 0, 0, 0.82);
display: flex; align-items: center; justify-content: center;
flex-direction: column; gap: 12px; cursor: zoom-out;
}
.lightbox img {
max-width: 88%; max-height: 82%;
border-radius: 8px; box-shadow: 0 8px 40px rgba(0, 0, 0, 0.5);
}
.lightbox-nav {
position: absolute; top: 50%; transform: translateY(-50%);
width: 40px; height: 64px; border: none; border-radius: 8px;
background: rgba(255, 255, 255, 0.12); color: #fff;
font-size: 30px; line-height: 1; cursor: pointer;
display: flex; align-items: center; justify-content: center;
transition: background .15s; user-select: none;
}
.lightbox-nav:hover { background: rgba(255, 255, 255, 0.28); }
.lightbox-nav.prev { left: 14px; }
.lightbox-nav.next { right: 14px; }
.lightbox-counter {
position: absolute; top: 14px; right: 16px;
background: rgba(0, 0, 0, 0.5); color: #fff;
font-size: 13px; padding: 3px 10px; border-radius: 999px;
font-variant-numeric: tabular-nums;
}
.lightbox-tip { color: rgba(255, 255, 255, 0.75); font-size: 12.5px; }
/* ── 出图方案 ── */
.plan-list { display: flex; flex-direction: column; gap: 4px; }
.plan-row {
display: flex; align-items: center; gap: 10px;
padding: 7px 10px; border: 1px solid var(--border); border-radius: 6px;
background: var(--card-soft);
}
.plan-row.off { opacity: .45; }
.plan-main { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; }
.plan-title { font-size: 13.5px; font-weight: 600; white-space: nowrap; }
.variant-chip {
flex-shrink: 0; font-size: 11.5px; padding: 0 8px; line-height: 1.8;
border-radius: 999px; background: #f3efff; border: 1px solid #ddd3fa; color: #6d28d9;
}
.plan-detail {
font-size: 12px; color: var(--text-2);
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.stepper { display: inline-flex; align-items: center; gap: 0; flex-shrink: 0; }
.step-btn {
width: 24px; height: 24px; border: 1px solid var(--border-strong); background: #fff;
border-radius: 5px; cursor: pointer; font-size: 14px; line-height: 1; color: var(--text);
display: inline-flex; align-items: center; justify-content: center;
}
.step-btn:hover:not([disabled]) { border-color: var(--primary); color: var(--primary); }
.step-btn[disabled] { opacity: .35; cursor: not-allowed; }
.step-num {
min-width: 28px; text-align: center; font-size: 13.5px; font-weight: 600;
font-variant-numeric: tabular-nums;
}
.ai-tag {
background: var(--primary); color: #fff; font-size: 11px;
border-radius: 4px; padding: 1px 6px; margin-right: 4px;
}
.hint { font-size: 12.5px; color: var(--text-2); line-height: 1.6; }
/* ── 模型下拉选项 ── */
.model-opt-name { font-size: 13.5px; font-weight: 600; color: var(--text); }
.model-opt-desc { font-size: 12px; color: var(--text-2); margin-top: 2px; }
.ok-chip {
display: inline-flex; align-items: center; gap: 5px;
background: #f6ffed; border: 1px solid #b7eb8f; color: #389e0d;
border-radius: 6px; padding: 4px 9px; font-size: 12.5px;
}
.warn-box {
background: var(--warn-bg); border: 1px solid var(--warn-border); color: var(--warn-text);
border-radius: 6px; padding: 7px 10px; font-size: 12.5px; margin-top: 6px; line-height: 1.6;
}
.empty {
text-align: center; color: var(--text-2); font-size: 13px;
padding: 22px 0; background: var(--card-soft); border-radius: 6px;
}
</style>
</head>
<body>
<div id="root"></div>
<script type="module" src="./App.tsx"></script>
</body>
</html>