统一 Airshelf 界面组件与图标

This commit is contained in:
iye
2026-05-27 12:29:41 +08:00
parent ea335587d2
commit 086d92991e
47 changed files with 750 additions and 450 deletions
+24 -14
View File
@@ -2,9 +2,9 @@
<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?v=202605211800">
<title>商品库 · Airshelf</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/restraint.css?v=2026052607">
<style>
/* ─── 全局 viewport 高度链 (让右侧 toolbar/分页吸顶吸底) ─── */
/* 整页滚动 · 头部 H1+actions sticky 固定 · 其他随页面滚 */
@@ -147,7 +147,7 @@
padding: 10px 12px;
border-top: 1px solid var(--border-faint);
font-size: 11.5px;
color: var(--black-alpha-56);
color: #6f6f6f;
background: var(--background-base);
}
.product-footer .stat {
@@ -170,9 +170,10 @@
.product-footer .stat[data-type]:hover svg { color: var(--heat); }
.product-footer .stat[data-type]:hover b { color: var(--heat); }
.product-footer .stat svg {
width: 13px; height: 13px;
color: var(--black-alpha-48);
width: 14px; height: 14px;
color: currentColor;
flex-shrink: 0;
stroke-width: 1.25;
transition: color var(--t-base);
}
.product-footer .stat b {
@@ -182,10 +183,11 @@
}
/* default ↔ hover 文本切换 */
.product-footer .stat .stat-hover { display: none; }
.product-footer .stat[data-type]:hover > svg { display: none; }
.product-footer .stat[data-type]:hover .stat-default { display: none; }
.product-footer .stat[data-type]:hover .stat-hover { display: inline; }
.product-footer .sep {
color: var(--black-alpha-24);
color: #b8b8b8;
font-family: var(--font-mono);
flex-shrink: 0;
}
@@ -627,8 +629,8 @@
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 01-2 2H5a2 2 0 01-2-2V5a2 2 0 012-2h11"/></svg>
<span class="btn-edit-label">管理商品</span>
</button>
<button class="btn btn-primary" type="button" id="open-new-product">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M12 5v14M5 12h14"/></svg>
<button class="btn btn-primary btn-create" type="button" id="open-new-product">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22V12"/><path d="M16 17h6"/><path d="M19 14v6"/><path d="M21 10.5V8a2 2 0 0 0-1-1.7l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.7l7 4a2 2 0 0 0 2 0l1.7-1"/><path d="m3.3 7 8.7 5 8.7-5"/><path d="m7.5 4.3 9 5.1"/></svg>
新建商品
</button>
</div>
@@ -1015,7 +1017,8 @@
<button type="button" id="bulk-exit">完成</button>
</div>
<script src="assets/shell.js?v=202605211643"></script>
<script src="assets/icons.js?v=2026052608"></script>
<script src="assets/shell.js?v=2026052607"></script>
<script>
Shell.render({ active: 'products', crumbs: [{ label: '工作台', href: 'index.html' }, { label: '商品库' }] });
@@ -1122,17 +1125,24 @@ cards.forEach(card => {
const label = m[1];
const num = m[2];
const isAsset = label === '素材';
const cta = isAsset ? '+ 去生成素材' : '+ 去生成视频';
const cta = isAsset ? '去生成素材' : '去生成视频';
const svg = stat.querySelector('svg');
// 重组结构: <svg> <span.stat-default>素材 <b>N</b></span> <span.stat-hover>+ 去生成素材</span>
const icon = window.IconKit
? window.IconKit.svg(isAsset ? 'images' : 'video', {
size: 14,
strokeWidth: 1.25,
className: 'product-stat-icon'
})
: (svg ? svg.outerHTML : '');
// 重组结构: <svg> <span.stat-default>素材 <b>N</b></span> <span.stat-hover>去生成素材</span>
stat.innerHTML = '';
if (svg) stat.appendChild(svg);
if (icon) stat.insertAdjacentHTML('beforeend', icon);
const dft = document.createElement('span');
dft.className = 'stat-default';
dft.innerHTML = `${label} <b>${num}</b>`;
const hv = document.createElement('span');
hv.className = 'stat-hover';
hv.textContent = cta;
hv.textContent = cta.replace(/^\s*\+\s*/, '');
stat.appendChild(dft);
stat.appendChild(hv);
stat.dataset.type = isAsset ? 'asset' : 'video';