| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844 |
- <!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>
|