Files
shanxia2.0/docs/fresh-mint-list-toolbar-date-shortcut-demo.html
T
zlwuandCursor 10c3c5470c chore: sync local PL/CRM/BX and migration work to new Gogs host
Bundle pending backend/web-admin feature updates, data-migration scripts,
and related docs so the V1.5 branch on the Tencent Cloud Gogs matches the
current workspace (excluding local secrets).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-01 09:19:21 +08:00

845 lines
31 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.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);
--radius: 10px;
}
* { 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: 1120px; 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: 760px; }
.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);
}
.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: 680px; }
.badge {
flex-shrink: 0;
display: inline-flex;
align-items: center;
height: 26px;
padding: 0 10px;
border-radius: 999px;
font-size: 12px;
font-weight: 600;
white-space: nowrap;
}
.badge-ok { background: var(--primary-bg); color: var(--primary-dark); }
.badge-mid { background: #eff6ff; color: #1d4ed8; }
.badge-bad { background: #fef2f2; color: #b91c1c; }
.panel {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
box-shadow: var(--shadow);
overflow: hidden;
}
.panel-top {
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: nowrap;
align-items: center;
justify-content: flex-start;
gap: 8px;
padding: 8px 16px;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
.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;
flex-shrink: 0;
}
.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;
flex-shrink: 0;
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; }
.quick-search {
height: 36px;
width: 200px;
max-width: 200px;
flex: 0 0 200px;
padding: 0 12px;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--surface);
font: inherit;
color: var(--text);
outline: none;
}
.quick-search:focus { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.15); }
.list-toolbar-end {
display: flex;
align-items: center;
gap: 4px;
margin-left: auto;
flex-shrink: 0;
padding-left: 8px;
}
.list-body { border-top: 1px solid var(--border); }
.fake-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.fake-table th, .fake-table td {
padding: 10px 14px;
text-align: left;
border-bottom: 1px solid #eef2f7;
}
.fake-table th {
background: #f8fafc;
color: var(--text-muted);
font-weight: 600;
}
.note {
margin: 12px 0 0;
padding: 12px 14px;
border-radius: 8px;
background: #f1f5f9;
color: var(--text-muted);
font-size: 13px;
}
.note strong { color: var(--text); }
.measure {
display: inline-flex;
align-items: center;
gap: 8px;
margin-bottom: 10px;
font-size: 12px;
color: var(--text-muted);
}
.px-tag {
display: inline-flex;
align-items: center;
height: 22px;
padding: 0 8px;
border-radius: 6px;
background: #e2e8f0;
color: #334155;
font-weight: 600;
font-variant-numeric: tabular-nums;
}
.viewport-frame {
border: 1px dashed #cbd5e1;
border-radius: 8px;
overflow: hidden;
resize: horizontal;
max-width: 100%;
min-width: 640px;
width: 100%;
}
/* —— 方案 0:现状五按钮 —— */
.chip-group {
display: inline-flex;
flex-wrap: nowrap;
gap: 6px;
padding-right: 8px;
margin-right: 4px;
border-right: 1px solid var(--border);
flex-shrink: 0;
}
.chip {
height: 32px;
padding: 0 10px;
border-radius: 8px;
border: 1px solid var(--border);
background: var(--surface);
color: var(--text);
font-size: 13px;
font-weight: 600;
font-family: inherit;
cursor: pointer;
white-space: nowrap;
}
.chip:hover { border-color: #b7d5cb; }
.chip.is-active {
border-color: var(--primary);
background: var(--primary-bg);
color: var(--primary-dark);
}
/* —— 方案 A:分段控件 —— */
.seg {
display: inline-flex;
align-items: stretch;
height: 32px;
padding: 2px;
border: 1px solid var(--border);
border-radius: 8px;
background: #f1f5f9;
flex-shrink: 0;
margin-right: 4px;
padding-right: 2px;
}
.seg + .quick-search,
.chip-group + .quick-search,
.date-select-wrap + .quick-search,
.date-trigger-wrap + .quick-search {
margin-left: 4px;
}
.seg-item {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 40px;
padding: 0 10px;
border: none;
border-radius: 6px;
background: transparent;
color: var(--text-muted);
font-size: 13px;
font-weight: 600;
font-family: inherit;
cursor: pointer;
white-space: nowrap;
}
.seg-item:hover { color: var(--text); }
.seg-item.is-active {
background: var(--surface);
color: var(--primary-dark);
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.08);
}
/* —— 方案 B:下拉选择 —— */
.date-select-wrap {
position: relative;
flex-shrink: 0;
margin-right: 4px;
}
.date-select {
appearance: none;
height: 36px;
min-width: 112px;
padding: 0 32px 0 12px;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--surface) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat right 10px center;
color: var(--text);
font: inherit;
font-weight: 600;
cursor: pointer;
outline: none;
}
.date-select:focus {
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.15);
}
/* —— 方案 C:日历触发 + 弹出菜单 —— */
.date-trigger-wrap {
position: relative;
flex-shrink: 0;
margin-right: 4px;
}
.date-trigger {
display: inline-flex;
align-items: center;
gap: 6px;
height: 36px;
padding: 0 12px;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--surface);
color: var(--text);
font: inherit;
font-weight: 600;
cursor: pointer;
}
.date-trigger:hover { border-color: #b7d5cb; background: #f8fafc; }
.date-trigger svg { width: 16px; height: 16px; color: var(--text-muted); }
.date-trigger .caret { width: 14px; height: 14px; }
.date-menu {
display: none;
position: absolute;
top: calc(100% + 6px);
left: 0;
z-index: 20;
min-width: 140px;
padding: 6px;
border: 1px solid var(--border);
border-radius: 10px;
background: var(--surface);
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.1);
}
.date-trigger-wrap.is-open .date-menu { display: block; }
.date-menu button {
display: flex;
width: 100%;
align-items: center;
height: 34px;
padding: 0 10px;
border: none;
border-radius: 6px;
background: transparent;
color: var(--text);
font: inherit;
font-weight: 500;
text-align: left;
cursor: pointer;
}
.date-menu button:hover { background: #f1f5f9; }
.date-menu button.is-active {
background: var(--primary-bg);
color: var(--primary-dark);
font-weight: 600;
}
.compare {
overflow: auto;
border: 1px solid var(--border);
border-radius: 10px;
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 #eef2f7;
vertical-align: top;
}
.compare th {
background: #f8fafc;
color: var(--text-muted);
font-weight: 600;
}
.compare tr:last-child td { border-bottom: none; }
.rec-mark { color: var(--primary-dark); font-weight: 700; }
.pick-bar {
position: sticky;
bottom: 0;
margin-top: 40px;
padding: 14px 16px;
border: 1px solid var(--border);
border-radius: 12px;
background: rgba(255, 255, 255, 0.92);
backdrop-filter: blur(8px);
box-shadow: 0 -4px 20px rgba(15, 23, 42, 0.06);
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 10px;
}
.pick-bar strong { margin-right: 4px; }
.pick-bar label {
display: inline-flex;
align-items: center;
gap: 6px;
height: 34px;
padding: 0 12px;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--surface);
cursor: pointer;
font-weight: 500;
}
.pick-bar label:has(input:checked) {
border-color: var(--primary);
background: var(--primary-bg);
color: var(--primary-dark);
font-weight: 600;
}
.pick-bar input { accent-color: var(--primary); }
</style>
</head>
<body>
<div class="demo-page">
<header class="demo-head">
<h1>日期快捷展示 · <span>Fresh Mint</span></h1>
<p>
运输计划等业务页把「已选 + 日期快捷 + 检索 + 操作按钮 + 刷新/列设置」收成<strong>一行</strong>时,
五个独立按钮(全部 / 昨日 / 今日 / 明日 / 本周)最占宽。以下对比三种更省空间的展示,拖拽虚线框右侧可模拟窄屏。
</p>
<nav class="toc">
<a href="#before">现状 · 五按钮</a>
<a class="rec" href="#a">推荐 · 分段控件</a>
<a href="#b">备选 · 下拉选择</a>
<a href="#c">备选 · 触发菜单</a>
<a href="#compare">对比表</a>
</nav>
</header>
<!-- 0 现状 -->
<section class="section" id="before">
<div class="section-head">
<div>
<h2>0. 现状:五个独立描边按钮</h2>
<p>与当前 <code>ListToolbarDateShortcuts</code> 一致。可发现性最好,但水平占位最大。</p>
</div>
<span class="badge badge-bad">占宽大</span>
</div>
<div class="measure">日期区宽约 <span class="px-tag" id="w0">—</span> px</div>
<div class="viewport-frame" style="width: 980px;">
<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">1</span> 项</div>
<div class="chip-group" id="measure0" data-group>
<button type="button" class="chip is-active" data-v="all">全部</button>
<button type="button" class="chip" data-v="yesterday">昨日</button>
<button type="button" class="chip" data-v="today">今日</button>
<button type="button" class="chip" data-v="tomorrow">明日</button>
<button type="button" class="chip" data-v="week">本周</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>
<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>YS-2026-001</td><td>2026-07-31</td><td>某某化工</td></tr></tbody>
</table>
</div>
</div>
</div>
<p class="note"><strong>问题:</strong>与大量业务按钮挤同一行时,窄屏必横向滚动或折行;日期快捷本身占约 280~320px。</p>
</section>
<!-- A 分段 -->
<section class="section" id="a">
<div class="section-head">
<div>
<h2>A. 分段控件(Segmented)</h2>
<p>五个选项合成一块控件,仍一眼可见、单击切换;外框共用,去掉按钮间隙与描边重复。</p>
</div>
<span class="badge badge-ok">推荐</span>
</div>
<div class="measure">日期区宽约 <span class="px-tag" id="wA">—</span> px</div>
<div class="viewport-frame" style="width: 980px;">
<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">1</span> 项</div>
<div class="seg" id="measureA" data-group role="group" aria-label="计划日期快捷筛选">
<button type="button" class="seg-item is-active" data-v="all">全部</button>
<button type="button" class="seg-item" data-v="yesterday">昨日</button>
<button type="button" class="seg-item" data-v="today">今日</button>
<button type="button" class="seg-item" data-v="tomorrow">明日</button>
<button type="button" class="seg-item" data-v="week">本周</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>
<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>YS-2026-001</td><td>2026-07-31</td><td>某某化工</td></tr></tbody>
</table>
</div>
</div>
</div>
<p class="note">
<strong>优点:</strong>仍保持「一眼五档」;比五按钮约省 40~70px,视觉更成组。
<strong>落地:</strong>可直接改 <code>ListToolbarDateShortcuts</code> 样式,API 不变。
</p>
</section>
<!-- B 下拉 -->
<section class="section" id="b">
<div class="section-head">
<div>
<h2>B. 下拉选择(Select)</h2>
<p>收成单个选择器,占宽最小;切换需多点一次。适合按钮极多的页。</p>
</div>
<span class="badge badge-mid">最省宽</span>
</div>
<div class="measure">日期区宽约 <span class="px-tag" id="wB">—</span> px</div>
<div class="viewport-frame" style="width: 980px;">
<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">1</span> 项</div>
<div class="date-select-wrap" id="measureB">
<select class="date-select" aria-label="计划日期快捷筛选">
<option value="all" selected>全部日期</option>
<option value="yesterday">昨日</option>
<option value="today">今日</option>
<option value="tomorrow">明日</option>
<option value="week">本周</option>
</select>
</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>
<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>YS-2026-001</td><td>2026-07-31</td><td>某某化工</td></tr></tbody>
</table>
</div>
</div>
</div>
<p class="note"><strong>取舍:</strong>占宽约 112px,单行最稳;但当前档位不再「平铺可见」,高频切「今日/明日」略慢。</p>
</section>
<!-- C 触发菜单 -->
<section class="section" id="c">
<div class="section-head">
<div>
<h2>C. 日历触发 + 弹出菜单</h2>
<p>显示当前选中文案(如「今日」),点击展开选项。形态接近 Element <code>el-dropdown</code>。</p>
</div>
<span class="badge badge-mid">备选</span>
</div>
<div class="measure">日期区宽约 <span class="px-tag" id="wC">—</span> px(随当前文案变化)</div>
<div class="viewport-frame" style="width: 980px;">
<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">1</span> 项</div>
<div class="date-trigger-wrap" id="measureC">
<button type="button" class="date-trigger" id="dateTriggerBtn" aria-haspopup="menu" aria-expanded="false">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="4" width="18" height="18" rx="2"/><path d="M16 2v4M8 2v4M3 10h18"/></svg>
<span id="dateTriggerLabel">全部</span>
<svg class="caret" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 9l6 6 6-6"/></svg>
</button>
<div class="date-menu" role="menu">
<button type="button" class="is-active" data-v="all" data-label="全部">全部</button>
<button type="button" data-v="yesterday" data-label="昨日">昨日</button>
<button type="button" data-v="today" data-label="今日">今日</button>
<button type="button" data-v="tomorrow" data-label="明日">明日</button>
<button type="button" data-v="week" data-label="本周">本周</button>
</div>
</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>
<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>YS-2026-001</td><td>2026-07-31</td><td>某某化工</td></tr></tbody>
</table>
</div>
</div>
</div>
<p class="note"><strong>适用:</strong>希望保留「当前筛选」可读文案,又不想平铺五档时。交互成本与 B 接近。</p>
</section>
<!-- 对比 -->
<section class="section" id="compare">
<div class="section-head">
<div>
<h2>对比与建议</h2>
<p>工具栏保持单行;优先换日期快捷形态,而不是把业务按钮拆到第二行。</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>弃用(单行场景)</td>
</tr>
<tr>
<td>A 分段控件</td>
<td>中</td>
<td>高</td>
<td>低(一击)</td>
<td>低(改组件样式)</td>
<td class="rec-mark">推荐默认</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>
</tbody>
</table>
</div>
</section>
<div class="pick-bar" id="pickBar">
<strong>选定方案:</strong>
<label><input type="radio" name="pick" value="A" checked /> A 分段控件</label>
<label><input type="radio" name="pick" value="B" /> B 下拉选择</label>
<label><input type="radio" name="pick" value="C" /> C 触发菜单</label>
<span style="margin-left: auto; color: var(--text-muted); font-size: 13px;">
选定后回复我选项代号即可落地到运输计划页
</span>
</div>
</div>
<script>
function bindGroup(root) {
if (!root) return
root.addEventListener('click', (e) => {
const btn = e.target.closest('[data-v]')
if (!btn || !root.contains(btn)) return
root.querySelectorAll('[data-v]').forEach((el) => el.classList.remove('is-active'))
btn.classList.add('is-active')
})
}
bindGroup(document.getElementById('measure0'))
bindGroup(document.getElementById('measureA'))
const wrapC = document.getElementById('measureC')
const btnC = document.getElementById('dateTriggerBtn')
const labelC = document.getElementById('dateTriggerLabel')
btnC.addEventListener('click', (e) => {
e.stopPropagation()
const open = wrapC.classList.toggle('is-open')
btnC.setAttribute('aria-expanded', open ? 'true' : 'false')
measure()
})
wrapC.querySelectorAll('.date-menu button').forEach((item) => {
item.addEventListener('click', (e) => {
e.stopPropagation()
wrapC.querySelectorAll('.date-menu button').forEach((el) => el.classList.remove('is-active'))
item.classList.add('is-active')
labelC.textContent = item.dataset.label
wrapC.classList.remove('is-open')
btnC.setAttribute('aria-expanded', 'false')
measure()
})
})
document.addEventListener('click', () => {
wrapC.classList.remove('is-open')
btnC.setAttribute('aria-expanded', 'false')
})
function measure() {
const set = (id, el) => {
const tag = document.getElementById(id)
if (tag && el) tag.textContent = Math.round(el.getBoundingClientRect().width)
}
set('w0', document.getElementById('measure0'))
set('wA', document.getElementById('measureA'))
set('wB', document.getElementById('measureB'))
set('wC', document.getElementById('measureC'))
}
measure()
window.addEventListener('resize', measure)
</script>
</body>
</html>