| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006 |
- <!doctype html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>Fresh Mint · 列表工具栏溢出优化 Demo</title>
- <link rel="preconnect" href="https://fonts.googleapis.com" />
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
- <style>
- :root {
- --primary: #10b981;
- --primary-dark: #059669;
- --primary-bg: #ecfdf5;
- --text: #1e293b;
- --text-muted: #64748b;
- --border: #d9e8e2;
- --surface: #ffffff;
- --table-head: #f8fafc;
- --bg-page: #f8fafc;
- --shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
- --shadow-lg: 0 8px 24px rgba(15, 23, 42, 0.1);
- --radius: 10px;
- --danger: #dc2626;
- }
- * { box-sizing: border-box; }
- body {
- margin: 0;
- min-height: 100vh;
- font-family: Inter, -apple-system, BlinkMacSystemFont, sans-serif;
- font-size: 14px;
- line-height: 1.5;
- color: var(--text);
- background: var(--bg-page);
- }
- .demo-page { max-width: 1100px; margin: 0 auto; padding: 32px 24px 80px; }
- .demo-head { margin-bottom: 28px; }
- .demo-head h1 {
- margin: 0 0 8px;
- font-size: 24px;
- font-weight: 700;
- letter-spacing: -0.02em;
- }
- .demo-head h1 span { color: var(--primary); }
- .demo-head p { margin: 0; color: var(--text-muted); max-width: 720px; }
- .toc {
- display: flex;
- flex-wrap: wrap;
- gap: 8px;
- margin: 20px 0 0;
- }
- .toc a {
- display: inline-flex;
- align-items: center;
- height: 32px;
- padding: 0 12px;
- border-radius: 8px;
- border: 1px solid var(--border);
- background: var(--surface);
- color: var(--text);
- text-decoration: none;
- font-size: 13px;
- font-weight: 500;
- }
- .toc a:hover { border-color: var(--primary); color: var(--primary-dark); background: var(--primary-bg); }
- .toc a.rec {
- border-color: var(--primary);
- background: var(--primary-bg);
- color: var(--primary-dark);
- }
- .toc a.probe {
- border-color: #93c5fd;
- background: #eff6ff;
- color: #1d4ed8;
- }
- .section { margin-top: 36px; }
- .section-head {
- display: flex;
- align-items: flex-start;
- justify-content: space-between;
- gap: 16px;
- margin-bottom: 12px;
- }
- .section-head h2 {
- margin: 0 0 4px;
- font-size: 18px;
- font-weight: 700;
- }
- .section-head p { margin: 0; color: var(--text-muted); font-size: 13px; max-width: 640px; }
- .badge {
- flex-shrink: 0;
- display: inline-flex;
- align-items: center;
- height: 26px;
- padding: 0 10px;
- border-radius: 999px;
- font-size: 12px;
- font-weight: 600;
- }
- .badge-bad { background: #fef2f2; color: var(--danger); }
- .badge-ok { background: var(--primary-bg); color: var(--primary-dark); }
- .badge-alt { background: #fff7ed; color: #c2410c; }
- .badge-probe { background: #eff6ff; color: #1d4ed8; }
- /* —— 文字按钮 —— */
- .btn-text {
- height: 36px;
- padding: 0 8px;
- border: none;
- background: transparent;
- color: var(--text);
- font-weight: 600;
- box-shadow: none;
- }
- .btn-text:hover {
- background: var(--primary-bg);
- color: var(--primary-dark);
- border: none;
- }
- .btn-text.btn-main {
- background: transparent;
- border: none;
- color: var(--primary-dark);
- }
- .btn-text.btn-main:hover {
- background: var(--primary-bg);
- color: var(--primary-dark);
- }
- .btn-text.danger { color: var(--danger); }
- .btn-text.danger:hover { background: #fef2f2; color: var(--danger); }
- .btn-text-only { padding: 0 6px; gap: 0; }
- .measure-row {
- display: grid;
- grid-template-columns: 1fr 1fr;
- gap: 12px;
- margin-bottom: 12px;
- }
- @media (max-width: 860px) {
- .measure-row { grid-template-columns: 1fr; }
- }
- .measure-card {
- border: 1px solid var(--border);
- border-radius: 10px;
- background: var(--surface);
- overflow: hidden;
- }
- .measure-card-head {
- display: flex;
- align-items: center;
- justify-content: space-between;
- gap: 8px;
- padding: 10px 12px;
- background: var(--table-head);
- border-bottom: 1px solid var(--border);
- font-size: 12px;
- font-weight: 600;
- color: var(--text-muted);
- }
- .measure-card-body {
- padding: 10px 12px;
- overflow-x: auto;
- }
- .measure-actions {
- display: inline-flex;
- align-items: center;
- gap: 4px;
- white-space: nowrap;
- }
- .measure-actions.ghost-gap { gap: 8px; }
- .px-tag {
- font-variant-numeric: tabular-nums;
- color: var(--primary-dark);
- font-weight: 700;
- }
- .panel {
- background: var(--surface);
- border: 1px solid var(--border);
- border-radius: var(--radius);
- box-shadow: var(--shadow);
- overflow: hidden;
- }
- .panel-top {
- display: flex;
- align-items: center;
- gap: 8px;
- padding: 14px 16px;
- border-bottom: 1px solid var(--border);
- }
- .panel-top h3 {
- margin: 0;
- font-size: 15px;
- font-weight: 700;
- position: relative;
- padding-left: 10px;
- }
- .panel-top h3::before {
- content: "";
- position: absolute;
- left: 0;
- top: 2px;
- bottom: 2px;
- width: 3px;
- border-radius: 2px;
- background: var(--primary);
- }
- /* —— 工具栏基线 —— */
- .list-toolbar { background: var(--table-head); }
- .list-toolbar-row {
- display: flex;
- flex-wrap: wrap;
- align-items: center;
- justify-content: flex-start;
- gap: 8px;
- padding: 8px 16px;
- }
- .list-toolbar-selected {
- display: inline-flex;
- align-items: center;
- min-height: 36px;
- padding: 0 10px 0 0;
- margin-right: 4px;
- border-right: 1px solid var(--border);
- font-size: 12px;
- font-weight: 600;
- color: var(--text-muted);
- white-space: nowrap;
- }
- .sel-num { color: var(--primary-dark); font-weight: 700; margin: 0 2px; }
- .btn {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- gap: 6px;
- height: 36px;
- padding: 0 14px;
- border-radius: 8px;
- border: 1px solid var(--border);
- background: var(--surface);
- color: var(--text);
- font-size: 14px;
- font-weight: 600;
- font-family: inherit;
- cursor: pointer;
- white-space: nowrap;
- transition: background .15s, border-color .15s, color .15s;
- }
- .btn:hover { border-color: #b7d5cb; background: #f8fafc; }
- .btn:disabled { opacity: .45; cursor: not-allowed; }
- .btn-main {
- background: var(--primary);
- border-color: var(--primary);
- color: #fff;
- }
- .btn-main:hover { background: var(--primary-dark); border-color: var(--primary-dark); color: #fff; }
- .btn-icon {
- width: 36px;
- min-width: 36px;
- padding: 0;
- border: none;
- background: transparent;
- color: var(--text-muted);
- }
- .btn-icon:hover { background: var(--primary-bg); color: var(--primary-dark); }
- .btn svg { width: 16px; height: 16px; flex-shrink: 0; }
- .chip-group {
- display: inline-flex;
- flex-wrap: wrap;
- gap: 6px;
- padding: 2px;
- }
- .chip {
- height: 28px;
- padding: 0 10px;
- border-radius: 6px;
- border: 1px solid var(--border);
- background: var(--surface);
- color: var(--text-muted);
- font-size: 12px;
- font-weight: 600;
- font-family: inherit;
- cursor: pointer;
- }
- .chip.is-active {
- background: var(--primary);
- border-color: var(--primary);
- color: #fff;
- }
- .quick-search {
- width: 220px;
- height: 36px;
- padding: 0 12px;
- border: 1px solid var(--border);
- border-radius: 8px;
- font-size: 13px;
- font-family: inherit;
- color: var(--text);
- background: var(--surface);
- }
- .quick-search::placeholder { color: #94a3b8; }
- .quick-search:focus {
- outline: none;
- border-color: var(--primary);
- box-shadow: 0 0 0 3px rgba(16, 185, 129, .15);
- }
- .list-toolbar-end {
- display: inline-flex;
- align-items: center;
- gap: 4px;
- margin-left: auto;
- }
- .list-body {
- border-top: 1px solid var(--border);
- padding: 0;
- }
- .fake-table {
- width: 100%;
- border-collapse: collapse;
- font-size: 13px;
- }
- .fake-table th,
- .fake-table td {
- padding: 10px 16px;
- text-align: left;
- border-bottom: 1px solid var(--border);
- }
- .fake-table th {
- background: var(--table-head);
- color: var(--text-muted);
- font-size: 12px;
- font-weight: 600;
- }
- .fake-table tbody tr:nth-child(even) td { background: #fafafa; }
- .note {
- margin-top: 10px;
- padding: 10px 12px;
- border-radius: 8px;
- background: #f1f5f9;
- color: var(--text-muted);
- font-size: 12px;
- }
- .note strong { color: var(--text); }
- /* —— 方案 A:更多下拉 —— */
- .toolbar-actions {
- display: inline-flex;
- flex-wrap: nowrap;
- align-items: center;
- gap: 8px;
- min-width: 0;
- }
- .more-wrap { position: relative; }
- .more-menu {
- display: none;
- position: absolute;
- top: calc(100% + 6px);
- right: 0;
- z-index: 20;
- min-width: 180px;
- padding: 6px;
- border: 1px solid var(--border);
- border-radius: 10px;
- background: var(--surface);
- box-shadow: var(--shadow-lg);
- }
- .more-wrap.is-open .more-menu { display: block; }
- .more-item {
- display: flex;
- align-items: center;
- gap: 8px;
- width: 100%;
- height: 36px;
- padding: 0 10px;
- border: none;
- border-radius: 8px;
- background: transparent;
- color: var(--text);
- font-size: 13px;
- font-weight: 500;
- font-family: inherit;
- cursor: pointer;
- text-align: left;
- }
- .more-item:hover { background: var(--primary-bg); color: var(--primary-dark); }
- .more-item:disabled { opacity: .45; cursor: not-allowed; }
- .more-item.danger { color: var(--danger); }
- .more-item.danger:hover { background: #fef2f2; color: var(--danger); }
- .more-divider {
- height: 1px;
- margin: 4px 6px;
- background: var(--border);
- }
- /* —— 方案 B:横向滚动 —— */
- .toolbar-scroll {
- display: flex;
- flex-wrap: nowrap;
- align-items: center;
- gap: 8px;
- min-width: 0;
- flex: 1;
- overflow-x: auto;
- -webkit-overflow-scrolling: touch;
- padding-bottom: 2px;
- scrollbar-width: thin;
- }
- .toolbar-scroll::-webkit-scrollbar { height: 4px; }
- .toolbar-scroll::-webkit-scrollbar-thumb {
- background: #cbd5e1;
- border-radius: 4px;
- }
- .list-toolbar-row.nowrap-row {
- flex-wrap: nowrap;
- }
- /* —— 方案 C:分区 —— */
- .toolbar-primary {
- display: inline-flex;
- align-items: center;
- gap: 8px;
- flex-wrap: nowrap;
- }
- .toolbar-meta {
- display: flex;
- flex-wrap: wrap;
- align-items: center;
- gap: 8px;
- padding: 6px 16px 10px;
- border-top: 1px dashed #e2e8f0;
- background: #fcfdfd;
- }
- .meta-label {
- font-size: 11px;
- font-weight: 600;
- color: var(--text-muted);
- letter-spacing: .02em;
- }
- .compare {
- margin-top: 28px;
- overflow: auto;
- border: 1px solid var(--border);
- border-radius: var(--radius);
- background: var(--surface);
- }
- .compare table { width: 100%; border-collapse: collapse; font-size: 13px; }
- .compare th, .compare td {
- padding: 12px 14px;
- text-align: left;
- border-bottom: 1px solid var(--border);
- vertical-align: top;
- }
- .compare th {
- background: var(--table-head);
- font-size: 12px;
- color: var(--text-muted);
- font-weight: 600;
- }
- .compare tr:last-child td { border-bottom: none; }
- .rec-mark { color: var(--primary-dark); font-weight: 700; }
- .width-hint {
- display: flex;
- align-items: center;
- gap: 10px;
- margin-bottom: 10px;
- font-size: 12px;
- color: var(--text-muted);
- }
- .width-hint input[type="range"] { width: 180px; accent-color: var(--primary); }
- .viewport-frame {
- border: 1px dashed #cbd5e1;
- border-radius: 8px;
- overflow: hidden;
- resize: horizontal;
- max-width: 100%;
- min-width: 480px;
- width: 100%;
- }
- </style>
- </head>
- <body>
- <div class="demo-page">
- <header class="demo-head">
- <h1>列表工具栏溢出优化 · <span>Fresh Mint</span></h1>
- <p>
- 当「已选计数 + 日期快捷 + 简易检索 + 业务按钮 + 刷新/列设置」挤在同一行时,
- <code>flex-wrap</code> 会折成两行。当前选定方向:
- <strong>列表工具栏带文案的操作按钮去掉前置图标</strong>(保留描边/主色实心形态),用更小的水平占位换单行概率。
- 右侧刷新/列设置仍为纯图标按钮,不受影响。
- </p>
- <nav class="toc">
- <a href="#before">现状(有图标)</a>
- <a class="rec" href="#d">选定 · 去掉前置图标</a>
- <a href="#a">备选 · 更多下拉</a>
- <a href="#b">备选 · 横向滚动</a>
- <a href="#c">备选 · 元信息下沉</a>
- <a href="#compare">对比表</a>
- </nav>
- </header>
- <!-- ========== 现状 ========== -->
- <section class="section" id="before">
- <div class="section-head">
- <div>
- <h2>0. 现状:全部平铺 → 折行</h2>
- <p>模拟合同列表工具栏:日期快捷 + 检索 + 8 个操作按钮,窄屏或中等宽度必折两行。</p>
- </div>
- <span class="badge badge-bad">需优化</span>
- </div>
- <div class="width-hint">
- 拖拽右侧边缘缩小容器宽度,观察折行:
- </div>
- <div class="viewport-frame" style="width: 920px;">
- <div class="panel">
- <div class="panel-top"><h3>合同列表</h3></div>
- <div class="list-toolbar">
- <div class="list-toolbar-row">
- <div class="list-toolbar-selected">已选 <span class="sel-num">2</span> 项</div>
- <div class="chip-group">
- <button type="button" class="chip is-active">全部</button>
- <button type="button" class="chip">昨日</button>
- <button type="button" class="chip">今日</button>
- <button type="button" class="chip">本周</button>
- </div>
- <input class="quick-search" placeholder="合同编号/名称/客户" />
- <button type="button" class="btn btn-main"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 5v14M5 12h14"/></svg>新增</button>
- <button type="button" class="btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 20h9M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg>编辑</button>
- <button type="button" class="btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 6h18M8 6V4h8v2M19 6l-1 14H6L5 6"/></svg>删除</button>
- <button type="button" class="btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16l4-2 4 2 4-2 4 2V8z"/></svg>提交审批</button>
- <button type="button" class="btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 6 9 17l-5-5"/></svg>审批通过</button>
- <button type="button" class="btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6 6 18M6 6l12 12"/></svg>审批驳回</button>
- <button type="button" class="btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12"/></svg>上传扫描件</button>
- <button type="button" class="btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3"/></svg>导出</button>
- <div class="list-toolbar-end">
- <button type="button" class="btn btn-icon" title="刷新" aria-label="刷新">
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12a9 9 0 1 1-2.6-6.3"/><path d="M21 3v6h-6"/></svg>
- </button>
- <button type="button" class="btn btn-icon" title="列设置" aria-label="列设置">
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg>
- </button>
- </div>
- </div>
- </div>
- <div class="list-body">
- <table class="fake-table">
- <thead><tr><th>合同编号</th><th>合同名称</th><th>状态</th></tr></thead>
- <tbody>
- <tr><td>HT-2026-001</td><td>某某化工原料采购合同</td><td>草稿</td></tr>
- <tr><td>HT-2026-002</td><td>年度框架协议</td><td>审批中</td></tr>
- </tbody>
- </table>
- </div>
- </div>
- </div>
- <p class="note"><strong>问题:</strong>折行后占用纵向空间,已选与主操作扫描节奏被打断;窄屏时第二行按钮不易被发现。</p>
- </section>
- <!-- ========== 选定:去掉前置图标 ========== -->
- <section class="section" id="d">
- <div class="section-head">
- <div>
- <h2>选定方案 · 工具栏文案按钮去掉前置图标</h2>
- <p>保留现有描边 / 主色实心按钮形态,只去掉文案前的图标与图标间距,降低每个按钮约 16px + gap 的占位。</p>
- </div>
- <span class="badge badge-ok">已选定</span>
- </div>
- <div class="measure-row">
- <div class="measure-card">
- <div class="measure-card-head">
- <span>有前置图标(现状)</span>
- <span>动作区宽约 <span class="px-tag" id="wGhost">—</span> px</span>
- </div>
- <div class="measure-card-body">
- <div class="measure-actions ghost-gap" id="measureGhost">
- <button type="button" class="btn btn-main"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 5v14M5 12h14"/></svg>新增</button>
- <button type="button" class="btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 20h9M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg>编辑</button>
- <button type="button" class="btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 6h18M8 6V4h8v2M19 6l-1 14H6L5 6"/></svg>删除</button>
- <button type="button" class="btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16l4-2 4 2 4-2 4 2V8z"/></svg>提交审批</button>
- <button type="button" class="btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 6 9 17l-5-5"/></svg>审批通过</button>
- <button type="button" class="btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6 6 18M6 6l12 12"/></svg>审批驳回</button>
- <button type="button" class="btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12"/></svg>上传扫描件</button>
- <button type="button" class="btn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3"/></svg>导出</button>
- </div>
- </div>
- </div>
- <div class="measure-card">
- <div class="measure-card-head">
- <span>无前置图标(选定)</span>
- <span>动作区宽约 <span class="px-tag" id="wTextOnly">—</span> px</span>
- </div>
- <div class="measure-card-body">
- <div class="measure-actions ghost-gap" id="measureTextOnly">
- <button type="button" class="btn btn-main">新增</button>
- <button type="button" class="btn">编辑</button>
- <button type="button" class="btn">删除</button>
- <button type="button" class="btn">提交审批</button>
- <button type="button" class="btn">审批通过</button>
- <button type="button" class="btn">审批驳回</button>
- <button type="button" class="btn">上传扫描件</button>
- <button type="button" class="btn">导出</button>
- </div>
- </div>
- </div>
- <div class="measure-card">
- <div class="measure-card-head">
- <span>对照:文字按钮仍带图标</span>
- <span>动作区宽约 <span class="px-tag" id="wText">—</span> px</span>
- </div>
- <div class="measure-card-body">
- <div class="measure-actions" id="measureText">
- <button type="button" class="btn btn-text btn-main"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 5v14M5 12h14"/></svg>新增</button>
- <button type="button" class="btn btn-text"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 20h9M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg>编辑</button>
- <button type="button" class="btn btn-text">删除</button>
- <button type="button" class="btn btn-text">提交审批</button>
- <button type="button" class="btn btn-text">审批通过</button>
- <button type="button" class="btn btn-text">审批驳回</button>
- <button type="button" class="btn btn-text">上传扫描件</button>
- <button type="button" class="btn btn-text">导出</button>
- </div>
- </div>
- </div>
- <div class="measure-card">
- <div class="measure-card-head">
- <span>节省幅度(相对「有图标描边」)</span>
- <span id="saveSummary" class="px-tag">—</span>
- </div>
- <div class="measure-card-body" style="color: var(--text-muted); font-size: 13px; line-height: 1.7;">
- <div>去掉前置图标:约省 <strong id="saveTextOnly">—</strong></div>
- <div>仅改文字按钮但仍留图标:约省 <strong id="saveText">—</strong></div>
- <div style="margin-top: 6px;">结论:在保留按钮形态的前提下,<strong>去图标比改文字链更划算、也更贴合现有视觉</strong>。</div>
- </div>
- </div>
- </div>
- <div class="width-hint">整行模拟(去图标后),拖窄观察折行是否缓解:</div>
- <div class="viewport-frame" style="width: 920px;">
- <div class="panel">
- <div class="panel-top"><h3>合同列表 · 无前置图标</h3></div>
- <div class="list-toolbar">
- <div class="list-toolbar-row">
- <div class="list-toolbar-selected">已选 <span class="sel-num">2</span> 项</div>
- <div class="chip-group">
- <button type="button" class="chip is-active">全部</button>
- <button type="button" class="chip">昨日</button>
- <button type="button" class="chip">今日</button>
- <button type="button" class="chip">本周</button>
- </div>
- <input class="quick-search" placeholder="合同编号/名称/客户" />
- <button type="button" class="btn btn-main">新增</button>
- <button type="button" class="btn">编辑</button>
- <button type="button" class="btn">删除</button>
- <button type="button" class="btn">提交审批</button>
- <button type="button" class="btn">审批通过</button>
- <button type="button" class="btn">审批驳回</button>
- <button type="button" class="btn">上传扫描件</button>
- <button type="button" class="btn">导出</button>
- <div class="list-toolbar-end">
- <button type="button" class="btn btn-icon" title="刷新" aria-label="刷新">
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12a9 9 0 1 1-2.6-6.3"/><path d="M21 3v6h-6"/></svg>
- </button>
- <button type="button" class="btn btn-icon" title="列设置" aria-label="列设置">
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg>
- </button>
- </div>
- </div>
- </div>
- <div class="list-body">
- <table class="fake-table">
- <thead><tr><th>合同编号</th><th>合同名称</th><th>状态</th></tr></thead>
- <tbody>
- <tr><td>HT-2026-001</td><td>某某化工原料采购合同</td><td>草稿</td></tr>
- </tbody>
- </table>
- </div>
- </div>
- </div>
- <p class="note">
- <strong>落地范围建议:</strong>仅列表工具栏 <code>.list-toolbar</code> 内「有文案的 el-button」去掉前置图标;
- 弹窗底栏、表格操作列、筛选区搜索/重置等可暂不改。
- 注意:现有 OpenSpec「按钮须携带图标」需同步放宽为「工具栏文案按钮可不带图标」。
- </p>
- </section>
- <!-- ========== 方案 A ========== -->
- <section class="section" id="a">
- <div class="section-head">
- <div>
- <h2>方案 A · 主操作外露 +「更多」下拉</h2>
- <p>高频主路径始终可见;低频/场景化动作收入「更多」。保持单行、左起扫描、仅首按钮主色。</p>
- </div>
- <span class="badge badge-alt">备选</span>
- </div>
- <div class="viewport-frame" style="width: 920px;">
- <div class="panel">
- <div class="panel-top"><h3>合同列表</h3></div>
- <div class="list-toolbar">
- <div class="list-toolbar-row nowrap-row">
- <div class="list-toolbar-selected">已选 <span class="sel-num">2</span> 项</div>
- <div class="toolbar-actions">
- <button type="button" class="btn btn-main">新增</button>
- <button type="button" class="btn">编辑</button>
- <button type="button" class="btn">删除</button>
- <button type="button" class="btn">提交审批</button>
- <div class="more-wrap" id="moreA">
- <button type="button" class="btn" id="moreABtn" aria-expanded="false" aria-haspopup="true">
- 更多
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 9l6 6 6-6"/></svg>
- </button>
- <div class="more-menu" role="menu">
- <button type="button" class="more-item" role="menuitem">上传扫描件</button>
- <button type="button" class="more-item" role="menuitem">导出</button>
- <div class="more-divider"></div>
- <button type="button" class="more-item" role="menuitem">审批通过</button>
- <button type="button" class="more-item" role="menuitem">审批驳回</button>
- <div class="more-divider"></div>
- <button type="button" class="more-item" role="menuitem">下载导入模板</button>
- <button type="button" class="more-item" role="menuitem">批量导入</button>
- </div>
- </div>
- </div>
- <div class="list-toolbar-end">
- <button type="button" class="btn btn-icon" title="刷新" aria-label="刷新">
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12a9 9 0 1 1-2.6-6.3"/><path d="M21 3v6h-6"/></svg>
- </button>
- <button type="button" class="btn btn-icon" title="列设置" aria-label="列设置">
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg>
- </button>
- </div>
- </div>
- </div>
- <div class="list-body">
- <table class="fake-table">
- <thead><tr><th>合同编号</th><th>合同名称</th><th>状态</th></tr></thead>
- <tbody>
- <tr><td>HT-2026-001</td><td>某某化工原料采购合同</td><td>草稿</td></tr>
- <tr><td>HT-2026-002</td><td>年度框架协议</td><td>审批中</td></tr>
- </tbody>
- </table>
- </div>
- </div>
- </div>
- <p class="note">
- <strong>收纳原则:</strong>
- ① 主创建/主编辑类外露;② 依赖选中行的低频动作(上传、导出、导入)进「更多」;
- ③ 场景切换型动作(审批通过/驳回)可按当前 Tab 动态外露或进「更多」;
- ④ 日期快捷与简易检索建议迁出工具栏(见方案 C),避免与操作按钮抢宽。
- 落地可用 Element Plus <code>el-dropdown</code>。
- </p>
- </section>
- <!-- ========== 方案 B ========== -->
- <section class="section" id="b">
- <div class="section-head">
- <div>
- <h2>方案 B · 单行不换行 + 横向滚动</h2>
- <p>工具栏 <code>flex-wrap: nowrap</code>,中间操作区 <code>overflow-x: auto</code>。实现成本低,但可发现性差。</p>
- </div>
- <span class="badge badge-alt">备选</span>
- </div>
- <div class="viewport-frame" style="width: 640px;">
- <div class="panel">
- <div class="panel-top"><h3>合同列表</h3></div>
- <div class="list-toolbar">
- <div class="list-toolbar-row nowrap-row">
- <div class="list-toolbar-selected">已选 <span class="sel-num">2</span> 项</div>
- <div class="toolbar-scroll">
- <button type="button" class="btn btn-main">新增</button>
- <button type="button" class="btn">编辑</button>
- <button type="button" class="btn">删除</button>
- <button type="button" class="btn">提交审批</button>
- <button type="button" class="btn">审批通过</button>
- <button type="button" class="btn">审批驳回</button>
- <button type="button" class="btn">上传扫描件</button>
- <button type="button" class="btn">导出</button>
- </div>
- <div class="list-toolbar-end">
- <button type="button" class="btn btn-icon" title="刷新" aria-label="刷新">
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12a9 9 0 1 1-2.6-6.3"/><path d="M21 3v6h-6"/></svg>
- </button>
- <button type="button" class="btn btn-icon" title="列设置" aria-label="列设置">
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg>
- </button>
- </div>
- </div>
- </div>
- <div class="list-body">
- <table class="fake-table">
- <thead><tr><th>合同编号</th><th>合同名称</th><th>状态</th></tr></thead>
- <tbody>
- <tr><td>HT-2026-001</td><td>某某化工原料采购合同</td><td>草稿</td></tr>
- </tbody>
- </table>
- </div>
- </div>
- </div>
- <p class="note"><strong>适用:</strong>临时兜底或按钮数量偶发超标的页。不推荐作为全站默认——右侧按钮容易被「藏」在滚动条外。</p>
- </section>
- <!-- ========== 方案 C ========== -->
- <section class="section" id="c">
- <div class="section-head">
- <div>
- <h2>方案 C · 元信息下沉 + 主操作区精简</h2>
- <p>把「日期快捷 / 简易检索」从操作行拆出(独立轻量条或并回筛选区),操作行只保留 CRUD + 更多。</p>
- </div>
- <span class="badge badge-ok">可与 A 组合</span>
- </div>
- <div class="viewport-frame" style="width: 920px;">
- <div class="panel">
- <div class="panel-top"><h3>合同列表</h3></div>
- <div class="list-toolbar">
- <div class="list-toolbar-row nowrap-row">
- <div class="list-toolbar-selected">已选 <span class="sel-num">2</span> 项</div>
- <div class="toolbar-primary">
- <button type="button" class="btn btn-main">新增</button>
- <button type="button" class="btn">编辑</button>
- <button type="button" class="btn">删除</button>
- <button type="button" class="btn">提交审批</button>
- <div class="more-wrap" id="moreC">
- <button type="button" class="btn" id="moreCBtn">
- 更多
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 9l6 6 6-6"/></svg>
- </button>
- <div class="more-menu" role="menu">
- <button type="button" class="more-item">上传扫描件</button>
- <button type="button" class="more-item">导出</button>
- <div class="more-divider"></div>
- <button type="button" class="more-item">审批通过</button>
- <button type="button" class="more-item">审批驳回</button>
- </div>
- </div>
- </div>
- <div class="list-toolbar-end">
- <button type="button" class="btn btn-icon" title="刷新" aria-label="刷新">
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12a9 9 0 1 1-2.6-6.3"/><path d="M21 3v6h-6"/></svg>
- </button>
- <button type="button" class="btn btn-icon" title="列设置" aria-label="列设置">
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg>
- </button>
- </div>
- </div>
- <div class="toolbar-meta">
- <span class="meta-label">快捷筛选</span>
- <div class="chip-group">
- <button type="button" class="chip is-active">全部</button>
- <button type="button" class="chip">昨日</button>
- <button type="button" class="chip">今日</button>
- <button type="button" class="chip">本周</button>
- </div>
- <input class="quick-search" placeholder="合同编号/名称/客户" style="margin-left: auto;" />
- </div>
- </div>
- <div class="list-body">
- <table class="fake-table">
- <thead><tr><th>合同编号</th><th>合同名称</th><th>状态</th></tr></thead>
- <tbody>
- <tr><td>HT-2026-001</td><td>某某化工原料采购合同</td><td>草稿</td></tr>
- <tr><td>HT-2026-002</td><td>年度框架协议</td><td>审批中</td></tr>
- </tbody>
- </table>
- </div>
- </div>
- </div>
- <p class="note">
- <strong>说明:</strong>这里用虚线次级条演示「元信息下沉」。产品上更干净的做法是:日期快捷/检索回到上方
- <code>filter-block</code>,工具栏只做「已选 → 动作 → 刷新/列设置」。
- </p>
- </section>
- <!-- ========== 对比 ========== -->
- <section class="section" id="compare">
- <div class="section-head">
- <div>
- <h2>对比与落地建议</h2>
- <p>全站默认建议 A;复杂业务页(合同/价格函)用 A + 把日期/检索移出操作行。</p>
- </div>
- </div>
- <div class="compare">
- <table>
- <thead>
- <tr>
- <th>方案</th>
- <th>单行稳定</th>
- <th>可发现性</th>
- <th>与规范兼容</th>
- <th>实现成本</th>
- <th>建议</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>去掉前置图标</td>
- <td>中高</td>
- <td>高</td>
- <td>需放宽「按钮必带图标」</td>
- <td>低</td>
- <td class="rec-mark">已选定</td>
- </tr>
- <tr>
- <td>A 更多下拉</td>
- <td>高</td>
- <td>中高</td>
- <td>高</td>
- <td>中</td>
- <td>备选</td>
- </tr>
- <tr>
- <td>B 横向滚动</td>
- <td>高</td>
- <td>低</td>
- <td>中</td>
- <td>低</td>
- <td>备选</td>
- </tr>
- <tr>
- <td>C 元信息下沉</td>
- <td>高(组合后)</td>
- <td>高</td>
- <td>高</td>
- <td>低~中</td>
- <td>备选</td>
- </tr>
- <tr>
- <td>全部平铺 + 有图标 + wrap</td>
- <td>低</td>
- <td>高但占高</td>
- <td>符合旧规范</td>
- <td>—</td>
- <td>弃用</td>
- </tr>
- </tbody>
- </table>
- </div>
- <p class="note" style="margin-top: 16px;">
- <strong>落地约定(草案):</strong>
- <code>.list-toolbar</code> 内带可见文案的操作按钮不再放前置 <code>el-icon</code>;
- 「刷新 / 列设置」等无文案图标钮保留;弹窗 footer、筛选区、表格操作列暂保持有图标。
- </p>
- </section>
- </div>
- <script>
- function bindMore(wrapId, btnId) {
- const wrap = document.getElementById(wrapId)
- const btn = document.getElementById(btnId)
- if (!wrap || !btn) return
- btn.addEventListener('click', (e) => {
- e.stopPropagation()
- const open = wrap.classList.toggle('is-open')
- btn.setAttribute('aria-expanded', open ? 'true' : 'false')
- document.querySelectorAll('.more-wrap.is-open').forEach((el) => {
- if (el !== wrap) {
- el.classList.remove('is-open')
- const b = el.querySelector('button')
- if (b) b.setAttribute('aria-expanded', 'false')
- }
- })
- })
- }
- bindMore('moreA', 'moreABtn')
- bindMore('moreC', 'moreCBtn')
- document.addEventListener('click', () => {
- document.querySelectorAll('.more-wrap.is-open').forEach((el) => {
- el.classList.remove('is-open')
- const b = el.querySelector('button')
- if (b) b.setAttribute('aria-expanded', 'false')
- })
- })
- function measureToolbarWidths() {
- const ghost = document.getElementById('measureGhost')
- const text = document.getElementById('measureText')
- const textOnly = document.getElementById('measureTextOnly')
- if (!ghost || !text || !textOnly) return
- const wG = Math.round(ghost.scrollWidth)
- const wT = Math.round(text.scrollWidth)
- const wO = Math.round(textOnly.scrollWidth)
- const set = (id, v) => { const el = document.getElementById(id); if (el) el.textContent = String(v) }
- set('wGhost', wG)
- set('wText', wT)
- set('wTextOnly', wO)
- const pct = (from, to) => ((from - to) / from * 100).toFixed(0) + '%(约 ' + (from - to) + 'px)'
- set('saveText', pct(wG, wT))
- set('saveTextOnly', pct(wG, wO))
- set('saveSummary', '最多约省 ' + pct(wG, wO))
- }
- measureToolbarWidths()
- window.addEventListener('resize', measureToolbarWidths)
- </script>
- </body>
- </html>
|