Files
shanxia2.0/docs/portal-worktab-capsule-v2-demo.html
T
2026-08-08 20:43:48 +08:00

455 lines
13 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" />
<title>门户 WorkTab · 胶囊居中 + 未激活态 Demo</title>
<style>
:root {
--primary: #10b981;
--primary-dark: #059669;
--primary-bg: #ecfdf5;
--header: #1ca851;
--text: #0f172a;
--muted: #64748b;
--border: #e2e8f0;
--surface: #ffffff;
--strip: #f1f5f9;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: Inter, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
color: var(--text);
background: #f8fafc;
line-height: 1.5;
}
.page { padding: 20px 24px 56px; max-width: 1120px; margin: 0 auto; }
h1 { font-size: 22px; margin: 0 0 6px; }
.lead { color: var(--muted); font-size: 14px; margin: 0 0 14px; }
.ok, .note {
border-radius: 10px;
padding: 10px 14px;
font-size: 13px;
margin-bottom: 12px;
}
.ok {
background: var(--primary-bg);
border: 1px solid #a7f3d0;
color: #065f46;
}
.note {
background: #fffbeb;
border: 1px solid #fde68a;
color: #92400e;
}
.compare {
display: grid;
gap: 20px;
}
@media (min-width: 900px) {
.compare { grid-template-columns: 1fr 1fr; }
}
.card-label {
display: flex;
justify-content: space-between;
align-items: baseline;
gap: 8px;
margin: 0 0 8px;
}
.card-label h2 { margin: 0; font-size: 15px; }
.card-label span { font-size: 12px; color: var(--muted); }
.frame {
border: 1px solid var(--border);
border-radius: 12px;
overflow: hidden;
background: #f8fafc;
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
}
.portal-header {
display: flex;
align-items: center;
gap: 10px;
height: 56px;
padding: 0 16px;
background: var(--header);
color: #fff;
}
.brand {
display: flex;
align-items: center;
gap: 8px;
font-weight: 600;
font-size: 15px;
}
.brand-mark {
width: 26px;
height: 26px;
border-radius: 7px;
background: rgba(255,255,255,0.2);
display: grid;
place-items: center;
font-size: 11px;
font-weight: 700;
}
.spacer { flex: 1; }
.user-chip {
width: 30px;
height: 30px;
border-radius: 999px;
background: rgba(255,255,255,0.22);
display: grid;
place-items: center;
font-size: 12px;
font-weight: 600;
}
.workspace { padding: 14px 16px 16px; }
.fake-panel {
background: #fff;
border: 1px solid var(--border);
border-radius: 10px;
padding: 14px 16px;
min-height: 96px;
}
.fake-panel h3 { margin: 0 0 4px; font-size: 15px; }
.fake-panel p { margin: 0; color: var(--muted); font-size: 13px; }
/* ========== 旧 B:未激活几乎看不见 ========== */
.old-strip {
display: flex;
align-items: center;
gap: 8px;
min-height: 44px;
padding: 6px 12px;
background: #f8fafc;
border-bottom: 1px solid var(--border);
}
.old-tabs {
display: flex;
flex: 1;
align-items: center;
gap: 6px;
min-width: 0;
overflow: hidden;
}
.old-chip {
appearance: none;
border: 1px solid transparent;
background: transparent;
color: var(--muted);
font-size: 13px;
font-weight: 500;
padding: 6px 10px 6px 12px;
border-radius: 8px;
cursor: pointer;
max-width: 150px;
display: inline-flex;
align-items: center;
gap: 6px;
white-space: nowrap;
}
.old-chip.is-active {
color: var(--primary-dark);
background: #fff;
border-color: #a7f3d0;
font-weight: 600;
box-shadow: 0 1px 2px rgba(16, 185, 129, 0.08);
}
.old-chip.is-home.is-active { background: var(--primary-bg); }
.old-x {
appearance: none;
border: 0;
background: transparent;
width: 18px;
height: 18px;
border-radius: 999px;
color: var(--muted);
cursor: pointer;
opacity: 0;
font-size: 14px;
padding: 0;
}
.old-chip:hover .old-x,
.old-chip.is-active .old-x { opacity: 0.75; }
.old-more {
width: 30px;
height: 30px;
border: 1px solid var(--border);
border-radius: 8px;
background: #fff;
color: var(--muted);
cursor: pointer;
flex-shrink: 0;
}
/* ========== 新 B:上下居中 + 未激活也有样式 ========== */
.new-strip {
display: flex;
align-items: center; /* 整行垂直居中 */
gap: 8px;
height: 48px; /* 固定条高,胶囊在此高度内居中 */
padding: 0 14px;
background: var(--strip);
border-bottom: 1px solid var(--border);
}
.new-tabs {
display: flex;
flex: 1;
align-items: center; /* Tab 与更多按钮同一中线 */
gap: 6px;
min-width: 0;
min-height: 100%;
overflow: hidden;
}
.new-chip {
appearance: none;
display: inline-flex;
align-items: center; /* 文案/关闭钮在胶囊内垂直居中 */
gap: 6px;
height: 32px; /* 固定胶囊高度,相对 48px 条带上下各 8px */
max-width: 160px;
padding: 0 8px 0 12px;
margin: 0;
font-size: 13px;
font-weight: 500;
line-height: 1;
color: #475569;
white-space: nowrap;
cursor: pointer;
background: #fff;
border: 1px solid #dbe3ec;
border-radius: 8px;
box-shadow: 0 1px 0 rgba(15, 23, 42, 0.02);
transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
}
.new-chip__label {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.new-chip:hover {
color: var(--text);
border-color: #cbd5e1;
background: #fff;
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.05);
}
.new-chip.is-active {
color: var(--primary-dark);
font-weight: 600;
background: #fff;
border-color: #6ee7b7;
box-shadow: 0 0 0 1px rgba(16, 185, 129, 0.12), 0 1px 2px rgba(16, 185, 129, 0.1);
}
.new-chip.is-home.is-active {
background: var(--primary-bg);
border-color: #6ee7b7;
}
.new-x {
appearance: none;
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
width: 18px;
height: 18px;
margin: 0;
padding: 0;
border: 0;
border-radius: 999px;
color: #94a3b8;
background: transparent;
cursor: pointer;
font-size: 14px;
line-height: 1;
opacity: 0;
transition: opacity 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.new-chip:hover .new-x,
.new-chip.is-active .new-x { opacity: 0.85; }
.new-x:hover {
opacity: 1 !important;
color: var(--text);
background: #f1f5f9;
}
.new-more {
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
width: 32px;
height: 32px;
margin: 0;
border: 1px solid #dbe3ec;
border-radius: 8px;
background: #fff;
color: var(--muted);
cursor: pointer;
box-shadow: 0 1px 0 rgba(15, 23, 42, 0.02);
}
.new-more:hover {
color: var(--primary-dark);
border-color: #a7f3d0;
background: var(--primary-bg);
}
.legend {
margin-top: 18px;
padding: 12px 14px;
background: #fff;
border: 1px solid var(--border);
border-radius: 10px;
font-size: 13px;
color: var(--muted);
}
.legend strong { color: var(--text); }
.legend code {
font-size: 12px;
background: #f1f5f9;
padding: 1px 6px;
border-radius: 4px;
}
</style>
</head>
<body>
<div class="page">
<h1>WorkTab 胶囊 · 上下居中 + 未激活态</h1>
<p class="lead">
左侧为上一版方案 B(未激活几乎透明);右侧为调整稿:条高固定、胶囊垂直居中,未激活也有白底描边。
</p>
<div class="ok">
<strong>已按右侧 B′ 落地</strong>
<code>web-admin/src/components/core/layouts/art-work-tab/index.vue</code>:
条带 48px 居中、胶囊 32px、未激活白底描边、激活薄荷绿边。
</div>
<div class="note">
可点击右侧 Demo 的 Tab 切换激活态;关闭钮为示意。
</div>
<div class="compare">
<!-- 旧 -->
<section>
<div class="card-label">
<h2>上一版 B</h2>
<span>未激活透明,辨识弱</span>
</div>
<div class="frame">
<header class="portal-header">
<div class="brand"><div class="brand-mark">SX</div><span>山峡化工一体化门户</span></div>
<div class="spacer"></div>
<div class="user-chip">管</div>
</header>
<div class="old-strip">
<div class="old-tabs" id="oldTabs"></div>
<button type="button" class="old-more">▾</button>
</div>
<div class="workspace">
<div class="fake-panel">
<h3>对比用</h3>
<p>未激活 Tab 几乎融进灰底,边界不清。</p>
</div>
</div>
</div>
</section>
<!-- 新 -->
<section>
<div class="card-label">
<h2>调整稿 B′(建议落地)</h2>
<span>居中 + 未激活有边</span>
</div>
<div class="frame">
<header class="portal-header">
<div class="brand"><div class="brand-mark">SX</div><span>山峡化工一体化门户</span></div>
<div class="spacer"></div>
<div class="user-chip">管</div>
</header>
<div class="new-strip">
<div class="new-tabs" id="newTabs"></div>
<button type="button" class="new-more" title="更多">▾</button>
</div>
<div class="workspace">
<div class="fake-panel">
<h3 id="pageTitle">首页</h3>
<p id="pageDesc">胶囊在 48px 条带内上下居中;未激活为白底描边胶囊。</p>
</div>
</div>
</div>
</section>
</div>
<div class="legend">
<strong>尺寸关系</strong>:条带 48px → 胶囊 32px → 上下各约 8px 空隙,保证垂直居中。
未激活:白底 <code>#fff</code> / 边 <code>#dbe3ec</code> / 字 <code>#475569</code>;
激活:字 <code>#059669</code>、边 <code>#6ee7b7</code>;首页激活额外浅绿底。
</div>
</div>
<script>
var TABS = [
{ id: 'home', title: '首页', fixed: true },
{ id: 'customer', title: '客户管理', fixed: false },
{ id: 'contract', title: '合同管理', fixed: false },
{ id: 'product', title: '产品管理', fixed: false },
{ id: 'plan', title: '运输计划', fixed: false }
]
var activeId = 'customer'
function render(containerId, prefix, interactive) {
var el = document.getElementById(containerId)
el.innerHTML = ''
TABS.forEach(function (tab) {
var chip = document.createElement('button')
chip.type = 'button'
chip.className =
prefix + '-chip' +
(tab.id === activeId ? ' is-active' : '') +
(tab.fixed ? ' is-home' : '')
var label = document.createElement('span')
if (prefix === 'new') label.className = 'new-chip__label'
label.textContent = tab.title
chip.appendChild(label)
if (!tab.fixed) {
var x = document.createElement('button')
x.type = 'button'
x.className = prefix + '-x'
x.textContent = '×'
x.setAttribute('aria-label', '关闭')
if (interactive) {
x.addEventListener('click', function (e) {
e.stopPropagation()
if (activeId === tab.id) activeId = 'home'
TABS = TABS.filter(function (t) { return t.id !== tab.id })
paint()
})
}
chip.appendChild(x)
}
if (interactive) {
chip.addEventListener('click', function () {
activeId = tab.id
paint()
})
}
el.appendChild(chip)
})
}
function paint() {
render('oldTabs', 'old', false)
render('newTabs', 'new', true)
var tab = TABS.find(function (t) { return t.id === activeId }) || TABS[0]
document.getElementById('pageTitle').textContent = tab.title
document.getElementById('pageDesc').textContent = tab.fixed
? '首页启动器占位。注意未激活胶囊也有白底描边。'
: '业务页占位。胶囊相对灰条垂直居中。'
}
paint()
</script>
</body>
</html>