fix(ui): 批量栏黑底还原 + 图片生成页排版对齐HTML + 视频卡去多余上传

- .bulk-bar 全局裸类被 admin-page.css 白底版盖掉 → 收窄到 .admin-app;
  商品库/项目/资产库批量浮条恢复黑底
- 批量浮条显隐改绑「有无选中」(.show)而非编辑模式 → 退选即消失
- asset-factory 三卡:开始生成按钮挪回 factory-text 内(对齐HTML),
  按钮紧跟描述、卡片高度回正;tag/desc/价格字号对齐HTML(10.5/13.5/10.5)
- 全站内容区上内边距 48px→24px(对齐设计稿 #page-content),标题不再整体偏低
- 视频卡移除多余「上传」按钮(AI生成不需单卡上传,全局上传入口保留);
  video-card-head 顶端对齐改垂直居中

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
seaislee1209
2026-06-20 18:34:33 +08:00
co-authored by Claude Opus 4.8
parent ad96acfacd
commit b946a64409
12 changed files with 193 additions and 21 deletions
+4 -2
View File
@@ -220,7 +220,9 @@
font-size: 11px;
cursor: help;
}
.bulk-bar {
/* 收窄到 .admin-app 作用域:`.bulk-bar` 是全局裸类(商品库/项目/资产库各有黑底版),
不限定会随 main.tsx 末位加载盖掉那些黑底浮条 → 全站批量栏被染白。 */
.admin-app .bulk-bar {
position: fixed;
left: 50%;
bottom: 28px;
@@ -235,7 +237,7 @@
box-shadow: var(--shadow-floating);
z-index: 50;
}
.bulk-count { font-size: 13px; color: var(--accent-black); font-weight: 500; }
.admin-app .bulk-count { font-size: 13px; color: var(--accent-black); font-weight: 500; }
/* ── 任务监控 ── */
.admin-anomaly-chip { height: 28px; padding: 0 14px; font-size: 12.5px; cursor: pointer; }
+3 -3
View File
@@ -44,7 +44,7 @@
.asset-factory .factory-tag {
align-self: flex-start;
font-family: var(--font-mono);
font-size: 12px;
font-size: 10.5px;
color: var(--black-alpha-48);
letter-spacing: .06em;
padding: 2px 8px;
@@ -62,7 +62,7 @@
}
.asset-factory .factory-desc {
margin-top: 8px;
font-size: 14px;
font-size: 13.5px;
color: var(--black-alpha-64);
line-height: 1.55;
}
@@ -77,7 +77,7 @@
}
.asset-factory .factory-cta .cost {
font-family: var(--font-mono);
font-size: 12px;
font-size: 10.5px;
color: var(--black-alpha-48);
letter-spacing: .04em;
}
+2 -1
View File
@@ -554,7 +554,8 @@ main { position: relative; background: var(--background-base); min-width: 0; }
/* ─── Content ─── */
.content {
padding: 48px 28px 72px;
/* 对齐 HTML 设计稿 #page-content(24px 28px 60px):原 48px 顶距使全站标题整体偏低 24px */
padding: 24px 28px 60px;
position: relative;
z-index: 1;
min-height: calc(100vh - 64px);
+2 -1
View File
@@ -54,7 +54,8 @@ body.edit-mode .library-page .asset-card .card-del-btn { opacity: 0 !important;
padding: 10px 14px 10px 18px; display: none; align-items: center; gap: 16px;
box-shadow: 0 8px 24px rgba(0, 0, 0, .18); z-index: 100; font-size: 13px;
}
body.edit-mode .lib-bulk-bar { display: inline-flex; }
/* 显隐绑定「是否有选中」而非编辑模式 → 退选即消失 */
.lib-bulk-bar.show { display: inline-flex; }
.lib-bulk-bar .ct { font-family: var(--font-mono); letter-spacing: .02em; }
.lib-bulk-bar .ct b { color: var(--heat); font-weight: 600; padding: 0 3px; }
.lib-bulk-bar .sep { width: 1px; height: 18px; background: rgba(255, 255, 255, .16); }
+1 -1
View File
@@ -448,7 +448,7 @@
.video-thumb:hover .play { opacity: 1; }
.video-thumb .btn-play { width: 36px; height: 36px; background: rgba(0,0,0,.7); color: var(--accent-white); border-radius: 50%; display: grid; place-items: center; }
.video-card .body { padding: 12px 12px 14px; flex: 1 1 auto; min-height: 118px; display: flex; flex-direction: column; }
.video-card-head { display: flex; align-items: flex-start; gap: 8px; }
.video-card-head { display: flex; align-items: center; gap: 8px; }
.video-card-title { min-width: 0; flex: 1 1 auto; font-size: 13px; line-height: 1.4; font-weight: 600; color: var(--accent-black); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.video-card-head .pill { flex: 0 0 auto; }
.video-meta { font-family: var(--font-mono); font-size: 12px; color: var(--black-alpha-48); letter-spacing: .02em; margin-top: 5px; }
+2 -1
View File
@@ -72,7 +72,8 @@ body.edit-mode .proj-card.selected { border-color: var(--heat); box-shadow: 0 0
padding: 10px 14px 10px 18px; display: none; align-items: center; gap: 16px;
box-shadow: 0 8px 24px rgba(0,0,0,.18); z-index: 100; font-size: 13px;
}
body.edit-mode .bulk-bar { display: inline-flex; }
/* 显隐绑定「是否有选中」而非编辑模式 → 退选即消失 */
.bulk-bar.show { display: inline-flex; }
.bulk-bar .ct { font-family: var(--font-mono); letter-spacing: .02em; }
.bulk-bar .ct b { color: var(--heat); font-weight: 700; padding: 0 3px; }
.bulk-bar .sep { width: 1px; height: 18px; background: rgba(255,255,255,.16); }
+9 -7
View File
@@ -210,13 +210,15 @@ export function AssetFactoryPage({ navigate }: { navigate: (page: Page) => void
<span className="factory-tag">{card.tag}</span>
<div className="factory-title">{card.title}</div>
<div className="factory-desc">{card.desc}</div>
</div>
<div className="factory-cta">
<button className="btn btn-primary btn-lg" type="button" onClick={() => navigate(card.page)}>
开始生成
<ArrowRight size={13} />
</button>
<span className="cost">[ {card.cost} ]</span>
{/* CTA 放在 factory-text 内(对齐 asset-factory.html):按钮紧跟描述,
而非被 factory-body 的 height:100% + margin-top:auto 顶到卡片最底部 */}
<div className="factory-cta">
<button className="btn btn-primary btn-lg" type="button" onClick={() => navigate(card.page)}>
开始生成
<ArrowRight size={14} />
</button>
<span className="cost">[ {card.cost} ]</span>
</div>
</div>
</div>
</article>
+1 -1
View File
@@ -695,7 +695,7 @@ export function LibraryPage({ onUpload, onDelete }: { onUpload: (formData: FormD
<Pager page={curPage} total={total} pageSize={LIB_PAGE_SIZE} onChange={setPage} />
{/* 编辑模式浮动批量操作栏(scope 到资产库;删除/清空/完成) */}
<div className="lib-bulk-bar" role="toolbar" aria-label="批量操作">
<div className={`lib-bulk-bar${selected.size > 0 ? " show" : ""}`} role="toolbar" aria-label="批量操作">
<span className="ct">已选 <b>{selected.size}</b> 项</span>
<button className="clear-sel" type="button" onClick={() => setSelected(new Set())}>清空</button>
<span className="sep" />
+1 -1
View File
@@ -2998,7 +2998,7 @@ export function PipelinePage(props: {
<div className="video-meta">{seg.target_duration_seconds}s · {timeline?.resolution || "1080×1920"} · ~¥0.45{seg.error_message ? ` · ${seg.error_message}` : ""}</div>
<div className="video-actions">
<button className="btn btn-ghost btn-sm" type="button" data-vstop disabled={loading || busy} onClick={() => guardGen(shots.filter((s) => s.sort_order === seg.sort_order), () => onSubmitVideo(seg.id, `${videoPrompt} 第 ${seg.sort_order + 1} 段,时长 ${seg.target_duration_seconds} 秒`))}>{busy ? "生成中…" : "重跑"}</button>
<button className="btn btn-ghost btn-sm" type="button" data-vstop disabled={loading} onClick={() => triggerVideoUpload(seg.id)}>上传</button>
{/* AI 生成片段不需单卡上传(自定义替换走 queue-bar 全局上传);移除多余「上传」按钮 */}
<span className="spacer"></span>
{url
? <a className="btn btn-ghost btn-sm" href={url} target="_blank" rel="noreferrer" data-vstop>下载</a>
+1 -1
View File
@@ -254,7 +254,7 @@ export function ProductsPage({ products, projects = [], loading = false, navigat
</div>
{/* 编辑模式浮动操作条 */}
<div className="bulk-bar" role="toolbar" aria-label="批量操作">
<div className={`bulk-bar${selected.size > 0 ? " show" : ""}`} role="toolbar" aria-label="批量操作">
<span className="ct">已选 <b>{selected.size}</b> 项</span>
<button className="clear-sel" type="button" onClick={() => setSelected(new Set())}>清空</button>
<span className="sep" />
+2 -2
View File
@@ -706,8 +706,8 @@ export function ProjectsPage({ products, projects, loading = false, navigate, op
<Pager page={curPage} total={filtered.length} pageSize={PROJ_PAGE_SIZE} onChange={setPage} />
{filtered.length === 0 && <EmptyPanel title="当前筛选下没有项目" action="新建视频项目" onAction={() => navigate("projectWizard")} />}
{/* 批量管理栏 · 编辑态吸底浮动(显隐由 body.edit-mode 控)· 蓝本同 products-page */}
<div className="bulk-bar" role="toolbar" aria-label="批量管理">
{/* 批量管理栏 · 吸底浮动(显隐绑「有无选中」)· 蓝本同 products-page */}
<div className={`bulk-bar${selected.size > 0 ? " show" : ""}`} role="toolbar" aria-label="批量管理">
<span className="ct">已选 <b>{selected.size}</b> 项</span>
<button className="clear-sel" type="button" disabled={selected.size === 0} onClick={() => setSelected(new Set())}>清空</button>
<span className="sep" />