Files
yingqing/core/frontend/src/product-detail-page.css
T
zycandClaude Fable 5 aab4d7ea4c fix: 测试清单遗留bug批量修复(15条:商品库/消费/团队/设置/消息中心/平台套图/资产库)
- R6 商品图删除不生效: 封面asset移交+绕开prefetch缓存, 前端封面缩图补删除入口
- R48 消息中心长文本与UI框错位: 胶囊单行省略+优先级标签禁压缩
- R70 账单流水筛选: 后端加ledger_type过滤, count随筛选变化, 切筛选重置页码
- R72 月限额改后不刷新: 团队页/消费页自取最新teamSettings, 两页同源
- R83/R86 平台套图提示词框加大+模型胶囊嵌入输入框(复用Pill组件)
- R96 未读角标: 修KeyTextTransform注解过滤触发MySQL 3141致接口500
- R100 工作台记录丢失: 新增GET /api/ai/tasks/workbench/ 同源恢复, 废除localStorage方案
- R104 卖点添加按钮移出输入框, 新建抽屉+编辑态统一
- R106 商品库宽屏锁5列, 10个/页铺满两行
- R108 资产删除改软删+单张删除+回收站二次确认; trash页商品/资产双分区+restore/purge端点
- R109 生成图自动入资产库(person演员立绘除外), 迁移0008存量回填, 移除全部加入资产库入口
- R65 无需改动(22268d6已修, 测旧部署所致)

验证: tsc/build/check/makemigrations --check 通过, 后端测试210/210, perf-probe PASS

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 11:30:06 +08:00

931 lines
31 KiB
CSS
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.
/* 商品详情页 · 从 public/exact/product-detail.html 内联 <style> 忠实移植,整段 scope 进 .product-detail-page 防冲突 */
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: .3; }
}
.product-detail-page {
/* ─── 顶部 标题 + 状态 ─── */
.pd-title {
display: flex; align-items: center; gap: 12px;
margin-bottom: 22px;
}
.pd-title h1 {
font-size: 24px; font-weight: 600;
letter-spacing: -.015em;
color: var(--accent-black);
line-height: 1.25;
}
.pd-title .status {
display: inline-flex; align-items: center; gap: 4px;
padding: 3px 10px;
background: var(--accent-emerald-bg, #e6f4ec);
color: var(--accent-emerald, #1f8a51);
border: 1px solid var(--accent-emerald-bd, #c4e3d1);
border-radius: var(--r-sm);
font-size: 12px;
font-weight: 500;
}
/* ─── 商品信息(含图片) + 快速操作(辅助) · 3 : 2 两栏 · 高度对齐 ─── */
.pd-overview {
display: grid;
grid-template-columns: 3fr 2fr;
gap: 16px;
margin-bottom: 24px;
align-items: stretch;
}
.pd-overview .ov-card { height: 100%; box-sizing: border-box; }
/* 编辑商品信息时左栏变高:右侧快速操作不跟随拉伸,而是锁定为进编辑前(查看态)的高度,
整体大小保持不变。高度值由组件用 ref 实测后内联到 .ov-actions(见 products.tsx)。 */
.pd-overview:has(.ov-main.editing) { align-items: start; }
.pd-overview .ov-card {
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-md);
padding: 20px 22px;
min-width: 0;
position: relative;
}
/* 编辑按钮 · 放在 .ov-h 标题行右侧 (flex item, 不再 absolute) */
.pd-overview .ov-h { align-items: center; }
.ov-edit {
display: inline-flex; align-items: center; gap: 5px;
height: 28px;
padding: 0 12px;
background: var(--surface);
border: 1px solid var(--black-alpha-12);
border-radius: var(--r-sm);
color: var(--black-alpha-72);
font-size: 12px;
font-family: inherit;
cursor: pointer;
white-space: nowrap;
transition: border-color var(--t-base), color var(--t-base), background var(--t-base);
}
.ov-edit-single { margin-left: auto; }
.ov-edit:hover {
border-color: var(--heat-40);
color: var(--heat);
background: var(--heat-12);
}
.ov-edit svg { width: 12px; height: 12px; }
.ov-edit.primary {
background: var(--heat);
color: var(--accent-white);
border-color: var(--heat);
white-space: nowrap;
}
.ov-edit.primary:hover { filter: brightness(1.05); background: var(--heat); color: var(--accent-white); }
.ov-edit:disabled { cursor: not-allowed; color: var(--heat); border-color: var(--heat-40); background: var(--heat-12); opacity: 1; }
.ov-edit:disabled:hover { color: var(--heat); border-color: var(--heat-40); background: var(--heat-12); }
.ov-edit:disabled svg { color: var(--heat); }
/* 编辑模式按钮组 (重置 + 取消 + 保存) */
.ov-edit-group {
display: none;
align-items: center;
gap: 6px;
margin-left: auto;
}
.ov-card.editing .ov-edit-single { display: none; }
.ov-card.editing .ov-edit-group { display: inline-flex; }
/* AI 生成三视图 · 按钮 + 弹出 panel(布局复刻 pipeline.html stage 2 三视图预览) */
.ov-tri-wrap { position: relative; margin-left: auto; }
/* 当 AI 入口存在时,编辑信息按钮不再独占 ml-auto,与 AI 按钮紧贴 */
.ov-tri-wrap + .ov-edit-single { margin-left: 0; }
.ov-tri-trigger { white-space: nowrap; }
.ov-tri-trigger.is-open { border-color: var(--heat); color: var(--heat); background: var(--heat-12); }
.ov-card.editing .ov-tri-wrap { display: none; }
.ov-tri-pop {
position: absolute;
top: calc(100% + 6px); right: 0;
width: 360px;
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-md);
box-shadow: 0 8px 24px rgba(0,0,0,.10), 0 2px 6px rgba(0,0,0,.06);
padding: 14px 14px 12px;
display: none;
flex-direction: column;
gap: 10px;
z-index: 40;
}
.ov-tri-pop.show { display: flex; }
.ov-tri-pop::before {
content: ''; position: absolute;
top: -5px; right: 36px;
width: 9px; height: 9px;
background: var(--surface);
border-left: 1px solid var(--border-faint);
border-top: 1px solid var(--border-faint);
transform: rotate(45deg);
}
.ov-tri-close {
position: absolute;
top: 8px; right: 8px;
width: 22px; height: 22px;
display: grid; place-items: center;
background: transparent;
border: 1px solid transparent;
border-radius: var(--r-sm);
color: var(--black-alpha-56);
cursor: pointer;
transition: background var(--t-base), color var(--t-base), border-color var(--t-base);
z-index: 2;
}
.ov-tri-close:hover { background: var(--black-alpha-08); color: var(--accent-black); border-color: var(--border-faint); }
.ov-tri-close svg { width: 12px; height: 12px; }
/* 复刻 pipeline.html .prod-preview-* 内部样式 */
.ov-tri-pop .prod-preview-h { display: flex; align-items: center; gap: 8px; font-family: var(--font-mono); font-size: 12px; color: var(--black-alpha-56); letter-spacing: .04em; text-transform: uppercase; padding-right: 28px; }
.ov-tri-pop .prod-preview-img { aspect-ratio: 16/9; }
.ov-tri-pop .prod-preview-foot { display: flex; align-items: center; gap: 8px; min-height: 30px; }
.ov-tri-pop .prod-preview-history { display: none; flex-direction: column; gap: 6px; }
.ov-tri-pop .prod-preview-history.show { display: flex; }
.ov-tri-pop .prod-preview-history .h-lbl { font-family: var(--font-mono); font-size: 12px; color: var(--black-alpha-48); letter-spacing: .04em; text-transform: uppercase; }
.ov-tri-pop .prod-preview-history .h-lbl .ct { color: var(--accent-black); font-weight: 600; }
.ov-tri-pop .prod-preview-history .h-row { display: flex; gap: 6px; overflow-x: auto; padding: 2px; scrollbar-width: thin; }
.ov-tri-pop .prod-preview-history .h-row::-webkit-scrollbar { height: 4px; }
.ov-tri-pop .prod-preview-history .h-row::-webkit-scrollbar-thumb { background: var(--border-faint); border-radius: 2px; }
.ov-tri-pop .prod-preview-history .h-thumb {
flex: 0 0 auto;
width: 72px; aspect-ratio: 16/9;
background: var(--background-lighter); border: 1px solid var(--border-faint); border-radius: var(--r-sm);
position: relative; cursor: pointer; transition: border-color var(--t-base);
display: grid; place-items: center; overflow: hidden;
}
.ov-tri-pop .prod-preview-history .h-thumb:hover { border-color: var(--heat-40); }
/* 已采用版本:主橙描边 + 「已采用」徽标 */
.ov-tri-pop .prod-preview-history .h-thumb.adopted { border-color: var(--heat); border-width: 2px; box-shadow: 0 0 0 2px var(--heat-12); }
/* 仅预览(未采用):黑色描边,无徽标 */
.ov-tri-pop .prod-preview-history .h-thumb.previewing { border-color: var(--accent-black); border-width: 2px; }
/* 缩略图带真图时,版本号加深色底片确保可读 */
.ov-tri-pop .prod-preview-history .h-thumb .v { font-family: var(--font-mono); font-size: 12px; color: var(--accent-white); letter-spacing: .02em; padding: 0 4px; border-radius: 3px; background: rgba(21,20,15,.56); }
.ov-tri-pop .prod-preview-history .h-thumb.adopted .v { font-weight: 600; }
.ov-tri-pop .prod-preview-history .h-thumb.previewing .v { font-weight: 600; }
.ov-tri-pop .prod-preview-history .h-thumb .badge { position: absolute; top: 2px; left: 2px; font-family: var(--font-mono); font-size: 12px; padding: 0 4px; line-height: 12px; background: var(--heat); color: var(--accent-white); border-radius: 2px; letter-spacing: .02em; display: none; }
.ov-tri-pop .prod-preview-history .h-thumb.adopted .badge { display: block; }
/* 主图可点击放大 */
.ov-tri-pop .prod-preview-img.is-zoomable { cursor: zoom-in; transition: border-color var(--t-base); position: relative; }
.ov-tri-pop .prod-preview-img.is-zoomable:hover { border-color: var(--heat-40); }
.ov-tri-pop .prod-preview-img.is-zoomable::after {
content: '';
position: absolute; top: 8px; right: 8px;
width: 22px; height: 22px;
background: rgba(21,20,15,.72) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='11' cy='11' r='7'/><path d='M21 21l-4.3-4.3M8 11h6M11 8v6'/></svg>") center/14px no-repeat;
border-radius: var(--r-sm);
opacity: 0; transition: opacity var(--t-base);
pointer-events: none;
}
.ov-tri-pop .prod-preview-img.is-zoomable:hover::after { opacity: 1; }
/* 三视图放大查看 lightbox */
#ov-tri-lightbox-bg { z-index: 80; }
#ov-tri-lightbox-bg .tri-lightbox {
position: relative;
width: min(1100px, 92vw);
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-md);
padding: 18px 20px 20px;
display: flex; flex-direction: column; gap: 12px;
box-shadow: 0 24px 64px rgba(0,0,0,.24);
}
.tri-lightbox-head {
display: flex; align-items: center; gap: 8px;
font-family: var(--font-mono);
font-size: 12px; letter-spacing: .04em; text-transform: uppercase;
color: var(--black-alpha-56);
padding-right: 32px;
}
.tri-lightbox-head .lb-ver { color: var(--heat); font-weight: 600; }
.tri-lightbox-head .lb-tag {
margin-left: 6px;
padding: 2px 6px;
background: var(--heat-12); color: var(--heat);
border-radius: 3px;
font-size: 12px;
}
.tri-lightbox-close {
position: absolute;
top: 12px; right: 12px;
width: 28px; height: 28px;
display: grid; place-items: center;
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-sm);
color: var(--black-alpha-56);
cursor: pointer;
transition: background var(--t-base), color var(--t-base), border-color var(--t-base);
z-index: 2;
}
.tri-lightbox-close:hover { background: var(--black-alpha-08); color: var(--accent-black); border-color: var(--black-alpha-12); }
.tri-lightbox-close svg { width: 14px; height: 14px; }
.tri-lightbox-img { aspect-ratio: 16/9; width: 100%; }
.tri-lightbox-foot { display: flex; align-items: center; gap: 8px; font-family: var(--font-mono); font-size: 12px; color: var(--black-alpha-48); }
.tri-lightbox-foot .spc { flex: 1; }
.tri-lightbox-foot kbd {
display: inline-block;
padding: 1px 5px;
background: var(--surface);
border: 1px solid var(--border-faint);
border-bottom-width: 2px;
border-radius: 3px;
font-family: var(--font-mono);
font-size: 12px;
color: var(--black-alpha-72);
}
/* 字段 view ↔ edit 状态切换 */
.v-edit { display: none; }
.ov-card.editing .v-static { display: none; }
.ov-card.editing .v-edit { display: block; }
/* 输入控件 · 对齐新建表单 V2.1 规范 */
.v-input,
.v-select {
width: 100%;
max-width: 100%;
height: 38px;
border: 1px solid var(--black-alpha-12);
border-radius: var(--r-md);
padding: 0 14px;
font-size: 14px;
color: var(--accent-black);
background: var(--background-lighter);
font-family: inherit;
outline: none;
transition: border-color var(--t-base), box-shadow var(--t-base);
}
.v-input:focus,
.v-select:focus {
border-color: var(--heat-40);
box-shadow: inset 0 0 0 1px var(--heat-40);
}
/* 编辑模式下 · 核心卖点 bullet-list (与新建表单完全一致) */
.v-bullet-list {
list-style: none;
padding: 0; margin: 0;
}
.v-bullet-list .bl-item,
.v-bullet-list .bl-add {
display: flex; align-items: center; gap: 10px;
padding: 8px 12px;
background: var(--background-lighter);
border: 1px solid var(--border-faint);
border-radius: var(--r-md);
margin-bottom: 6px;
font-size: 14px;
}
.v-bullet-list .bl-add { background: transparent; border-style: dashed; }
.v-bullet-list .bl-add:focus-within { border-color: var(--heat-40); background: var(--surface); }
.v-bullet-list .num {
width: 22px; height: 22px;
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-sm);
font-family: var(--font-mono);
font-size: 12px;
color: var(--heat);
font-weight: 600;
display: grid; place-items: center;
flex-shrink: 0;
}
.v-bullet-list .bl-add .num {
background: transparent;
color: var(--heat);
border-color: var(--heat-40);
}
.v-bullet-list .bl-text { flex: 1; color: var(--accent-black); }
.v-bullet-list .bl-input {
flex: 1;
background: transparent; border: 0; outline: none;
font-size: 14px;
color: var(--accent-black);
font-family: inherit;
}
.v-bullet-list .bl-input::placeholder { color: var(--black-alpha-48); }
.v-bullet-list .bl-x {
width: 22px; height: 22px;
color: var(--black-alpha-48);
cursor: pointer;
display: grid; place-items: center;
border-radius: var(--r-sm);
transition: color var(--t-base), background var(--t-base);
}
.v-bullet-list .bl-x:hover { color: var(--accent-crimson, #c43d3d); background: var(--crimson-bg, #fdebea); }
.v-bullet-list .bl-x svg { width: 11px; height: 11px; }
/* R104:显式「添加卖点」按钮(列表下方独立小按钮,不再是嵌在列表里的「+ 输入框」),
与新建商品抽屉 .bl-add-btn 同观感;仅编辑态显示(覆盖 .v-edit 的 display:block)。 */
.bl-add-btn {
align-items: center; gap: 5px;
height: 26px; padding: 0 10px; margin-top: 2px;
background: var(--surface);
border: 1px solid var(--border-loud); border-radius: var(--r-sm);
font-size: 12px; color: var(--accent-black); font-family: inherit; cursor: pointer;
transition: background var(--t-base), border-color var(--t-base), color var(--t-base);
}
.ov-card.editing .v-edit.bl-add-btn { display: inline-flex; }
.bl-add-btn:hover { background: var(--heat-12); border-color: var(--heat-40); color: var(--heat); }
.bl-add-btn svg { width: 12px; height: 12px; }
/* 编辑模式下,商品图片显示一个 [+ 上传] 占位 */
.img-upload {
display: none;
aspect-ratio: 1;
border: 1.5px dashed var(--black-alpha-24);
border-radius: var(--r-sm);
cursor: pointer;
place-items: center;
color: var(--black-alpha-48);
background: var(--background-lighter);
transition: border-color var(--t-base), color var(--t-base);
}
.img-upload:hover { border-color: var(--heat); color: var(--heat); }
.img-upload svg { width: 18px; height: 18px; }
.ov-card.editing .img-upload { display: grid; }
/* 编辑态:可删的图(有 ProductImage 关联)右上角显示删除 X;整块点击即删 */
.ov-card.editing .ov-images-sub .thumb.is-del { cursor: pointer; }
.ov-card.editing .ov-images-sub .thumb.is-del::after {
content: '×';
position: absolute;
top: 4px; right: 4px;
width: 18px; height: 18px;
background: rgba(0,0,0,.7);
color: var(--accent-white);
border-radius: 50%;
display: grid; place-items: center;
font-size: 13px;
line-height: 1;
pointer-events: none;
}
.ov-card.editing .ov-images-sub .thumb.is-del:hover::after { background: var(--heat); }
.ov-images-sub .thumb { position: relative; }
.pd-overview .ov-h {
display: flex; align-items: baseline; gap: 8px;
margin-bottom: 14px;
}
.pd-overview .ov-h .ti {
font-size: 14px; font-weight: 600;
color: var(--accent-black);
}
.pd-overview .ov-h .ct {
font-family: var(--font-mono);
font-size: 12px;
color: var(--black-alpha-48);
letter-spacing: .02em;
}
.pd-overview .ov-h .more {
margin-left: auto;
font-size: 12px;
color: var(--heat);
cursor: pointer;
}
.pd-overview .ov-h .more:hover { text-decoration: underline; }
/* 商品信息卡片内 · 上信息 / 下图片 (堆叠, 图片铺满卡片) */
.ov-main-grid {
display: flex;
flex-direction: column;
gap: 18px;
}
.ov-main-grid > .ov-images-sub {
padding-top: 18px;
border-top: 1px solid var(--border-faint);
}
.ov-info .row {
display: flex; gap: 12px;
margin-bottom: 10px;
font-size: 13px;
}
.ov-info .row:last-child { margin-bottom: 0; }
.ov-info .k {
width: 64px;
flex-shrink: 0;
color: var(--black-alpha-48);
font-size: 13px;
}
.ov-info .v {
flex: 1; min-width: 0;
color: var(--accent-black);
line-height: 1.6;
}
.ov-info .v .bullet { display: block; }
.ov-info .v .bullet::before {
content: '·';
color: var(--heat);
margin-right: 6px;
font-weight: 600;
}
/* 商品图片 · 卡片内子 section */
.ov-images-sub .sub-h {
display: flex; align-items: baseline; gap: 6px;
margin-bottom: 10px;
}
.ov-images-sub .sub-h .ti {
font-size: 13px; font-weight: 500;
color: var(--black-alpha-72);
}
.ov-images-sub .sub-h .ct {
font-family: var(--font-mono);
font-size: 12px;
color: var(--black-alpha-48);
letter-spacing: .02em;
}
.ov-images-sub .sub-h .more {
margin-left: auto;
font-size: 12px;
color: var(--heat);
cursor: pointer;
}
.ov-images-sub .sub-h .more:hover { text-decoration: underline; }
.ov-images-sub .grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
gap: 8px;
}
.ov-images-sub .thumb {
aspect-ratio: 1;
border-radius: var(--r-sm);
overflow: hidden;
cursor: pointer;
}
.ov-images-sub .thumb img { width: 100%; height: 100%; object-fit: cover; }
/* 快速操作 · 2 段:图片生成(3 等比 CTA)+ 视频生成(1 CTA) · 两段等高填充容器 */
.ov-actions { display: flex; flex-direction: column; }
.ov-actions .qa-section {
margin-bottom: 14px;
display: flex; flex-direction: column;
flex: 1 1 0; min-height: 0;
}
.ov-actions .qa-section:last-child { margin-bottom: 0; }
.ov-actions .qa-section-h {
font-family: var(--font-mono);
font-size: 12px;
color: var(--black-alpha-48);
letter-spacing: .06em;
text-transform: uppercase;
margin-bottom: 8px;
}
.ov-actions .qa-row-3 {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8px;
flex: 1 1 0; min-height: 0;
}
.ov-actions .qa-row-1 {
display: flex;
flex: 1 1 0; min-height: 0;
}
.ov-actions .qa-row-1 .qa-item { width: 100%; }
.qa-item {
display: flex; flex-direction: column;
align-items: center; justify-content: center; gap: 8px;
padding: 14px 10px;
background: var(--background-lighter);
border: 1px solid var(--border-faint);
border-radius: var(--r-md);
cursor: pointer;
font-size: 13px;
color: var(--accent-black);
text-align: center;
transition: border-color var(--t-base), background var(--t-base), color var(--t-base);
}
.qa-item:hover { border-color: var(--heat); background: var(--heat-12); color: var(--heat); }
.qa-item .ic {
width: 32px; height: 32px;
display: grid; place-items: center;
color: var(--heat);
flex-shrink: 0;
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-sm);
}
.qa-item:hover .ic { border-color: var(--heat); background: var(--surface); }
.qa-item .ic svg { width: 16px; height: 16px; }
.qa-item.primary {
background: var(--heat);
color: var(--accent-white);
border-color: var(--heat);
}
.qa-item.primary .ic { background: var(--accent-white); color: var(--heat); border-color: var(--accent-white); }
.qa-item.primary:hover { color: var(--accent-white); box-shadow: var(--shadow-cta-hover); }
/* 审核状态 pill 三态(通过/不通过/待审核)· 只读,不再可点(去 cursor:pointer) */
.asset-card .meta .pill.pass {
background: var(--accent-emerald-bg, #e6f4ec);
color: var(--accent-emerald, #1f8a51);
border: 1px solid var(--accent-emerald-bd, #c4e3d1);
}
.asset-card .meta .pill.fail {
background: var(--crimson-bg, #fdebea);
color: var(--accent-crimson, #c43d3d);
border: 1px solid var(--crimson-bd, #f5c2bf);
}
.asset-card .meta .pill.pending {
background: var(--background-lighter);
color: var(--black-alpha-56);
border: 1px solid var(--border-faint);
}
/* ─── Tabs ─── */
.pd-tabs {
display: flex; gap: 4px;
border-bottom: 1px solid var(--border-faint);
margin-bottom: 18px;
}
.pd-tabs .tab {
padding: 10px 14px;
font-size: 14px;
color: var(--black-alpha-56);
background: transparent;
border: 0;
border-bottom: 2px solid transparent;
cursor: pointer;
font-family: inherit;
font-weight: 500;
transition: color var(--t-base), border-color var(--t-base);
}
.pd-tabs .tab:hover { color: var(--accent-black); }
.pd-tabs .tab.active {
color: var(--accent-black);
border-bottom-color: var(--heat);
font-weight: 600;
}
.tab-pane { display: none; }
.tab-pane.active { display: block; }
/* ─── AI 素材 工具栏 ─── */
.pd-toolbar {
display: flex; align-items: center; gap: 10px;
margin-bottom: 14px;
flex-wrap: wrap;
}
.pd-toolbar .total {
font-size: 14px; font-weight: 600;
color: var(--accent-black);
}
.pd-toolbar .total .ct {
font-family: var(--font-mono);
font-size: 12px;
color: var(--black-alpha-48);
letter-spacing: .02em;
margin-left: 4px;
font-weight: 500;
}
.pd-toolbar .filter {
display: inline-flex; align-items: center; gap: 4px;
height: 30px;
padding: 0 10px;
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-sm);
cursor: pointer;
font-size: 13px;
color: var(--black-alpha-72);
font-family: inherit;
transition: border-color var(--t-base), color var(--t-base);
}
.pd-toolbar .filter:hover { border-color: var(--black-alpha-24); }
.pd-toolbar .filter.open, .pd-toolbar .filter.filtered { border-color: var(--heat); color: var(--heat); background: var(--heat-12); }
.pd-toolbar .filter.open svg, .pd-toolbar .filter.filtered svg { color: var(--heat); }
.pd-toolbar .filter svg { width: 10px; height: 10px; color: var(--ink-3); transition: transform var(--t-base), color var(--t-base); }
.pd-toolbar .filter.open svg { transform: rotate(180deg); }
/* 筛选下拉 · 挂在 body 上避免被祖先 overflow 裁切 */
.filter-pop {
position: fixed;
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-md);
padding: 4px;
box-shadow: 0 6px 20px var(--black-alpha-12);
z-index: 1500;
min-width: 130px;
display: none;
flex-direction: column;
}
.filter-pop.show { display: flex; }
.filter-pop button {
background: transparent; border: 0;
padding: 8px 12px;
text-align: left;
font-size: 13px;
color: var(--accent-black);
cursor: pointer;
border-radius: var(--r-sm);
font-family: inherit;
white-space: nowrap;
transition: background var(--t-base);
}
.filter-pop button:hover { background: var(--background-lighter); }
.filter-pop button.selected { background: var(--heat-12); color: var(--heat); font-weight: 600; }
.filter-pop button.selected::before { content: '✓ '; }
.pd-toolbar .right { margin-left: auto; display: inline-flex; align-items: center; gap: 8px; }
.pd-toolbar .view-tog {
display: inline-flex;
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-sm);
padding: 2px;
}
.pd-toolbar .view-tog button {
width: 28px; height: 26px;
display: grid; place-items: center;
border: 0;
background: transparent;
color: var(--black-alpha-48);
cursor: pointer;
border-radius: 4px;
}
.pd-toolbar .view-tog button.active {
background: var(--accent-black);
color: var(--accent-white);
}
.pd-toolbar .view-tog button svg { width: 13px; height: 13px; }
/* ─── AI 素材 网格 ─── */
.asset-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
gap: 12px;
}
/* 列表视图:卡片横排,缩略图缩到 88px */
.asset-grid.list-view {
display: flex;
flex-direction: column;
gap: 6px;
}
.asset-grid.list-view .asset-card {
display: grid;
grid-template-columns: 88px minmax(0, 1fr);
gap: 0;
align-items: center;
}
.asset-grid.list-view .asset-card .thumb {
aspect-ratio: 1;
width: 88px;
border-right: 1px solid var(--border-faint);
}
.asset-grid.list-view .asset-card .thumb .type-pill {
font-size: 12px;
padding: 2px 6px;
top: 4px;
left: 4px;
}
.asset-grid.list-view .asset-card .thumb .ph-frame { font-size: 12px; }
.asset-grid.list-view .asset-card .meta {
padding: 10px 14px;
}
/* 空筛选结果 */
.empty-filter {
padding: 56px 24px;
text-align: center;
color: var(--black-alpha-48);
font-family: var(--font-mono);
font-size: 13px;
letter-spacing: .02em;
border: 1px dashed var(--border-faint);
border-radius: var(--r-md);
background: var(--background-lighter);
}
.empty-filter .reset {
display: inline-block; margin-top: 12px;
color: var(--heat); cursor: pointer; text-decoration: underline;
}
.asset-card {
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-md);
overflow: hidden;
cursor: pointer;
transition: border-color var(--t-base), transform var(--t-fast);
}
.asset-card:hover { border-color: var(--black-alpha-24); transform: translateY(-1px); }
.asset-card .thumb {
aspect-ratio: 3/4;
position: relative;
overflow: hidden;
}
/* 有 preview_url 显真图:铺满缩图、cover 裁切、继承圆角 */
.asset-card .thumb img { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: inherit; }
.asset-card .thumb .type-pill {
position: absolute; top: 8px; left: 8px;
padding: 3px 8px;
background: rgba(0,0,0,.65);
color: var(--accent-white);
border-radius: var(--r-sm);
font-size: 12px;
font-weight: 500;
backdrop-filter: blur(4px);
}
.asset-card .meta {
padding: 10px 12px;
display: flex; align-items: center; gap: 8px;
}
.asset-card .meta .pill {
padding: 2px 8px;
border-radius: var(--r-sm);
font-size: 12px;
font-weight: 500;
}
.asset-card .meta .date {
margin-left: auto;
font-family: var(--font-mono);
font-size: 12px;
color: var(--black-alpha-48);
letter-spacing: .02em;
}
.pd-more {
text-align: center;
padding: 18px 0 32px;
}
.pd-more button {
height: 32px;
padding: 0 18px;
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-md);
color: var(--black-alpha-72);
font-size: 13px;
font-family: inherit;
cursor: pointer;
}
.pd-more button:hover { border-color: var(--heat-40); color: var(--heat); }
/* ─── 任务记录 · 表格 ─── */
.task-stats {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px;
margin-bottom: 18px;
}
.task-stat {
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-md);
padding: 14px 18px;
}
.task-stat .lbl {
font-family: var(--font-mono);
font-size: 12px;
color: var(--black-alpha-48);
letter-spacing: .04em;
margin-bottom: 6px;
}
.task-stat .v {
font-size: 22px; font-weight: 600;
color: var(--accent-black);
letter-spacing: -.01em;
}
.task-stat .v small {
font-size: 13px;
color: var(--black-alpha-48);
font-weight: 400;
margin-left: 4px;
}
.task-stat.ok .v { color: var(--accent-emerald, #1f8a51); }
.task-stat.gen .v { color: var(--heat); }
.task-stat.err .v { color: var(--accent-crimson, #c43d3d); }
.task-table {
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-md);
overflow: hidden;
}
.task-row {
display: grid;
grid-template-columns: 36px 1.8fr 0.7fr 1fr 1.1fr 1.1fr 0.7fr 100px;
align-items: center;
gap: 12px;
padding: 12px 18px;
border-bottom: 1px solid var(--border-faint);
font-size: 13px;
}
.task-row:last-child { border-bottom: 0; }
.task-row.head {
background: var(--background-lighter);
font-family: var(--font-mono);
font-size: 12px;
color: var(--black-alpha-48);
letter-spacing: .04em;
font-weight: 500;
padding: 10px 18px;
}
.task-row .ph {
width: 36px; height: 36px;
border-radius: var(--r-sm);
flex-shrink: 0;
}
.task-row .nm {
color: var(--accent-black);
font-weight: 500;
display: flex; align-items: center; gap: 8px;
}
.task-row .nm .id-mono {
font-family: var(--font-mono);
font-size: 12px;
color: var(--black-alpha-48);
font-weight: 400;
}
.task-row .qty { color: var(--black-alpha-72); font-family: var(--font-mono); }
.task-row .time {
color: var(--black-alpha-72);
font-family: var(--font-mono);
font-size: 12px;
letter-spacing: .01em;
}
.task-row .dur {
color: var(--black-alpha-56);
font-family: var(--font-mono);
font-size: 12px;
}
.task-row .pill {
display: inline-flex; align-items: center; gap: 5px;
padding: 3px 9px;
border-radius: var(--r-sm);
font-size: 12px;
font-weight: 500;
width: fit-content;
}
.task-row .pill .dot {
width: 6px; height: 6px;
border-radius: 50%;
}
.task-row .pill.ok {
background: var(--accent-emerald-bg, #e6f4ec);
color: var(--accent-emerald, #1f8a51);
border: 1px solid var(--accent-emerald-bd, #c4e3d1);
}
.task-row .pill.ok .dot { background: var(--accent-emerald, #1f8a51); }
.task-row .pill.gen {
background: var(--heat-12);
color: var(--heat);
border: 1px solid var(--heat-20);
}
.task-row .pill.gen .dot { background: var(--heat); animation: pulse 1.6s ease-in-out infinite; }
.task-row .pill.err {
background: var(--crimson-bg, #fdebea);
color: var(--accent-crimson, #c43d3d);
border: 1px solid var(--crimson-bd, #f5c2bf);
}
.task-row .pill.err .dot { background: var(--accent-crimson, #c43d3d); }
.task-row .pill.wait {
background: var(--background-lighter);
color: var(--black-alpha-56);
border: 1px solid var(--border-faint);
}
.task-row .pill.wait .dot { background: var(--black-alpha-32); }
.task-row .status-cell { display: flex; flex-direction: column; gap: 4px; }
.task-row .progress {
width: 100%; height: 3px;
background: var(--black-alpha-12);
border-radius: 2px;
overflow: hidden;
}
.task-row .progress > span {
display: block;
height: 100%;
background: var(--heat);
}
.task-row .ops {
display: inline-flex; gap: 4px;
justify-self: end;
}
.task-row .ops button {
padding: 4px 10px;
height: 26px;
background: transparent;
border: 1px solid var(--border-faint);
border-radius: var(--r-sm);
color: var(--black-alpha-72);
font-size: 12px;
font-family: inherit;
cursor: pointer;
transition: border-color var(--t-base), color var(--t-base);
}
.task-row .ops button:hover { border-color: var(--heat-40); color: var(--heat); }
.task-row .ops button.danger:hover { border-color: var(--crimson-bd, #f5c2bf); color: var(--accent-crimson, #c43d3d); }
@media (max-width: 1100px) {
.pd-overview { grid-template-columns: 1fr; }
.ov-actions .qa-grid {
display: grid !important;
grid-template-columns: repeat(3, 1fr);
}
}
@media (max-width: 900px) {
.ov-actions .qa-grid { grid-template-columns: 1fr 1fr; }
.task-stats { grid-template-columns: repeat(2, 1fr); }
}
}