Files
shanxia2.0/docs/superpowers/demos/2026-09-30-pl-plan-archive-pair-list-demo.html
T
2026-10-02 09:28:00 +08:00

667 lines
30 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>运输计划归档 · 一行一装一送 列表方案对比</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;
--row-alt: #fafafa;
--row-hover: #f1f5f9;
--bg-page: #f1f5f9;
--shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
--radius: 10px;
--warn: #d97706;
--warn-bg: #fffbeb;
--load-accent: #059669;
--load-bg: #ecfdf5;
--load-border: #a7f3d0;
--delivery-accent: #0284c7;
--delivery-bg: #f0f9ff;
--delivery-border: #bae6fd;
--danger: #dc2626;
--info: #0369a1;
--info-bg: #f0f9ff;
}
* { 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);
}
.page { max-width: 1480px; margin: 0 auto; padding: 24px 20px 80px; }
.hero {
background: linear-gradient(135deg, #ecfdf5 0%, #fff 55%, #f0f9ff 100%);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 22px 24px;
margin-bottom: 16px;
box-shadow: var(--shadow);
}
.hero h1 { margin: 0 0 8px; font-size: 22px; font-weight: 700; }
.hero h1 em { font-style: normal; color: var(--primary-dark); }
.hero p { margin: 0; color: var(--text-muted); max-width: 980px; }
.pills { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.pill {
display: inline-flex; align-items: center; gap: 6px;
padding: 4px 10px; border-radius: 999px; font-size: 12px; font-weight: 500;
background: var(--primary-bg); color: var(--primary-dark); border: 1px solid var(--load-border);
}
.pill.blue { background: var(--delivery-bg); color: var(--delivery-accent); border-color: var(--delivery-border); }
.pill.muted { background: #f1f5f9; color: var(--text-muted); border-color: #e2e8f0; }
.pill.warn { background: var(--warn-bg); color: var(--warn); border-color: #fde68a; }
.scheme-tabs {
display: flex; flex-wrap: wrap; gap: 6px;
background: #fff; border: 1px solid var(--border);
border-radius: var(--radius) var(--radius) 0 0; padding: 10px 12px 0;
}
.scheme-tab {
border: none; background: transparent; cursor: pointer;
padding: 10px 14px; font-size: 13px; font-weight: 600;
color: var(--text-muted); border-bottom: 2px solid transparent; font-family: inherit;
}
.scheme-tab:hover { color: var(--primary-dark); }
.scheme-tab.active { color: var(--primary-dark); border-bottom-color: var(--primary); }
.scheme-tab.recommended::after {
content: "推荐"; margin-left: 6px; font-size: 10px; font-weight: 700;
color: #fff; background: var(--primary-dark); padding: 1px 6px; border-radius: 999px;
vertical-align: middle;
}
.scheme-panel {
display: none; background: #fff; border: 1px solid var(--border); border-top: none;
border-radius: 0 0 var(--radius) var(--radius); padding: 16px 18px 22px; box-shadow: var(--shadow);
}
.scheme-panel.active { display: block; }
.scheme-desc {
margin: 0 0 14px; padding: 12px 14px; border-radius: 8px; font-size: 13px;
border: 1px solid #bae6fd; background: var(--info-bg); color: var(--info);
}
.scheme-desc strong { color: var(--text); }
.scheme-meta {
display: flex; flex-wrap: wrap; gap: 8px; margin: -4px 0 14px;
}
.meta-chip {
font-size: 12px; padding: 3px 8px; border-radius: 6px;
background: #f8fafc; border: 1px solid #e2e8f0; color: var(--text-muted);
}
.meta-chip.pro { border-color: var(--load-border); background: var(--load-bg); color: var(--load-accent); }
.meta-chip.con { border-color: #fecaca; background: #fef2f2; color: var(--danger); }
.filter-hint {
display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
margin-bottom: 12px; padding: 10px 12px;
background: #fffbeb; border: 1px dashed #fde68a; border-radius: 8px;
font-size: 12px; color: #92400e;
}
.filter-hint .tag {
display: inline-flex; align-items: center; gap: 4px;
padding: 2px 8px; border-radius: 999px; background: #fff; border: 1px solid #fde68a;
font-weight: 600; color: var(--warn);
}
.table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: 8px; }
table.list {
width: 100%; border-collapse: collapse; min-width: 1100px;
font-size: 13px;
}
table.list th, table.list td {
border-bottom: 1px solid var(--border);
padding: 10px 12px;
vertical-align: middle;
text-align: left;
}
table.list th {
background: var(--table-head);
font-size: 12px; font-weight: 600; color: var(--text-muted);
white-space: nowrap;
position: sticky; top: 0; z-index: 1;
}
table.list th.center, table.list td.center { text-align: center; }
table.list tbody tr:nth-child(even) { background: var(--row-alt); }
table.list tbody tr:hover { background: var(--row-hover); }
table.list tbody tr.plan-alt { background: #f8fafc; }
table.list tbody tr.plan-alt:hover { background: var(--row-hover); }
table.list .merge-cell {
background: #fff;
border-right: 1px solid var(--border);
vertical-align: top;
}
a.plan-link { color: var(--primary-dark); font-weight: 600; text-decoration: none; }
a.plan-link:hover { text-decoration: underline; }
.status-tag {
display: inline-block; padding: 2px 8px; border-radius: 4px;
font-size: 12px; font-weight: 600; color: #fff; background: var(--primary-dark);
}
.status-tag.draft { background: var(--warn); }
.status-tag.info { background: transparent; color: var(--text); border: 1px solid var(--border); font-weight: 500; }
.side-label {
display: inline-block; font-size: 10px; font-weight: 700; letter-spacing: 0.02em;
padding: 1px 6px; border-radius: 4px; margin-right: 6px; vertical-align: middle;
}
.side-label.load { background: var(--load-bg); color: var(--load-accent); border: 1px solid var(--load-border); }
.side-label.delivery { background: var(--delivery-bg); color: var(--delivery-accent); border: 1px solid var(--delivery-border); }
.stack-cell { display: flex; flex-direction: column; gap: 6px; }
.stack-row {
display: flex; align-items: flex-start; gap: 6px;
padding: 6px 8px; border-radius: 6px;
}
.stack-row.load { background: var(--load-bg); border: 1px solid var(--load-border); }
.stack-row.delivery { background: var(--delivery-bg); border: 1px solid var(--delivery-border); }
.stack-row .body { flex: 1; min-width: 0; }
.stack-row .name { font-weight: 600; color: var(--text); }
.stack-row .sub { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
.internal-tag {
display: inline-block; margin-left: 6px; padding: 0 5px;
font-size: 10px; font-weight: 700; color: #fff; background: var(--primary-dark);
border-radius: 3px; vertical-align: middle;
}
th.group-load, td.col-load { background: rgba(236, 253, 245, 0.45); }
th.group-delivery, td.col-delivery { background: rgba(240, 249, 255, 0.55); }
th.group-load { color: var(--load-accent); border-bottom: 2px solid var(--load-border); }
th.group-delivery { color: var(--delivery-accent); border-bottom: 2px solid var(--delivery-border); }
table.list thead tr.group-row th {
text-align: center; font-size: 12px; padding: 6px 10px;
}
table.list thead tr.group-row th.group-load { background: var(--load-bg); }
table.list thead tr.group-row th.group-delivery { background: var(--delivery-bg); }
table.list thead tr.subhead th { font-size: 11px; padding: 8px 10px; }
.qty { font-variant-numeric: tabular-nums; white-space: nowrap; }
.muted { color: var(--text-muted); }
.addr { font-size: 12px; color: var(--text-muted); max-width: 160px; }
.product-line { font-size: 12px; }
.product-line + .product-line { margin-top: 2px; color: var(--text-muted); }
.legend {
margin-top: 16px; padding: 12px 14px; border-radius: 8px;
background: #f8fafc; border: 1px solid #e2e8f0; font-size: 12px; color: var(--text-muted);
}
.legend h3 { margin: 0 0 6px; font-size: 13px; color: var(--text); }
.legend ul { margin: 0; padding-left: 18px; }
.legend li { margin: 2px 0; }
.current-badge {
display: inline-block; font-size: 10px; font-weight: 700;
padding: 1px 6px; border-radius: 999px; margin-left: 6px;
background: #fee2e2; color: #b91c1c; vertical-align: middle;
}
</style>
</head>
<body>
<div class="page">
<header class="hero">
<h1>运输计划归档 · <em>一行一装一送</em> 列表方案对比</h1>
<p>
同一份示例数据:计划 <strong>JH260330-001</strong> 有 1 个装货 + 2 个送货;
计划 <strong>JH260330-002</strong> 有 1 个装货 + 1 个送货。
方案 A 为<strong>现状(按段次拆行)</strong>;B~D 为「每一行 = 一个装货对应一个送货」。
底部用「客户筛选:华东化纤」演示筛选后是否还能看到对侧客户。
</p>
<div class="pills">
<span class="pill">Fresh Mint 色板</span>
<span class="pill">装货侧 · 绿</span>
<span class="pill blue">送货侧 · 蓝</span>
<span class="pill warn">关注:客户筛选后信息完整性</span>
<span class="pill muted">仅 Demo,未改业务代码</span>
</div>
</header>
<nav class="scheme-tabs" role="tablist" aria-label="列表方案">
<button type="button" class="scheme-tab active" data-scheme="a" role="tab" aria-selected="true">A · 现状:按段次拆行</button>
<button type="button" class="scheme-tab recommended" data-scheme="b" role="tab" aria-selected="false">B · 拆成两套列</button>
<button type="button" class="scheme-tab" data-scheme="c" role="tab" aria-selected="false">C · 一格上下叠放</button>
<button type="button" class="scheme-tab" data-scheme="d" role="tab" aria-selected="false">D · 表头分组列</button>
</nav>
<!-- ========== A 现状 ========== -->
<section class="scheme-panel active" id="scheme-a" role="tabpanel">
<p class="scheme-desc">
<strong>现状:</strong>装货一行、每个送货各一行。「客户」列只显示当前段客户。
若按「华东化纤」筛选,只会留下送货行,<strong>看不到装货客户「宜昌港务」</strong>——这正是用户反馈的痛点。
</p>
<div class="scheme-meta">
<span class="meta-chip con">筛选后丢对侧信息</span>
<span class="meta-chip con">扫一眼难看清装→送关系</span>
<span class="meta-chip">列数少、与其它运输计划列表一致</span>
</div>
<div class="filter-hint">
<span>模拟筛选</span>
<span class="tag">客户 = 华东化纤</span>
<span>→ 只剩送货段行,装货侧信息消失</span>
</div>
<div class="table-wrap">
<table class="list">
<thead>
<tr>
<th>计划编号</th>
<th class="center">计划日期</th>
<th class="center">归档</th>
<th class="center">车牌</th>
<th class="center">段次</th>
<th>客户</th>
<th>地址 / 时间</th>
<th>产品</th>
<th class="center">数量</th>
</tr>
</thead>
<tbody>
<tr>
<td class="merge-cell" rowspan="2"><a class="plan-link" href="#">JH260330-001</a></td>
<td class="merge-cell center" rowspan="2">2026-03-30</td>
<td class="merge-cell center" rowspan="2"><span class="status-tag">已归档</span></td>
<td class="merge-cell center" rowspan="2">鄂E·A1234</td>
<td class="center"><span class="side-label load">装货</span></td>
<td>宜昌港务<span class="internal-tag">内部</span></td>
<td><div>港区 3 号仓</div><div class="muted">03-30 08:00</div></td>
<td>
<div class="product-line">尿素 · 50kg</div>
<div class="product-line">复合肥 · 25kg</div>
</td>
<td class="center qty">32 / 18</td>
</tr>
<tr>
<td class="center"><span class="side-label delivery">送货 #1</span></td>
<td>华东化纤</td>
<td><div>苏州工业园…</div><div class="muted">03-30 14:00</div></td>
<td><div class="product-line">尿素 · 50kg</div></td>
<td class="center qty">20</td>
</tr>
<tr class="plan-alt">
<td class="merge-cell" rowspan="2"><a class="plan-link" href="#">JH260330-001</a> <span class="current-badge">筛选后</span></td>
<td class="merge-cell center" rowspan="2">2026-03-30</td>
<td class="merge-cell center" rowspan="2"><span class="status-tag">已归档</span></td>
<td class="merge-cell center" rowspan="2">鄂E·A1234</td>
<td class="center"><span class="side-label delivery">送货 #1</span></td>
<td>华东化纤</td>
<td><div>苏州工业园…</div><div class="muted">03-30 14:00</div></td>
<td><div class="product-line">尿素 · 50kg</div></td>
<td class="center qty">20</td>
</tr>
<tr class="plan-alt">
<td colspan="5" class="muted" style="font-size:12px;background:#fef2f2;color:#b91c1c;">
↑ 装货行被过滤掉了 —— 「宜昌港务 / 港区 3 号仓」不可见
</td>
</tr>
</tbody>
</table>
</div>
<div class="legend">
<h3>说明</h3>
<ul>
<li>上半:未筛选时的完整段次展开(1 装 + 2 送会占 3 行,Demo 只示意前两行)。</li>
<li>下半:客户筛选「华东化纤」后,只剩送货行。</li>
</ul>
</div>
</section>
<!-- ========== B 拆列 ========== -->
<section class="scheme-panel" id="scheme-b" role="tabpanel">
<p class="scheme-desc">
<strong>方案 B(推荐):</strong>每行 = 装货 × 一个送货。客户/地址拆成
<strong>装货客户 | 送货客户 | 装货地址 | 送货地址</strong> 等独立列。
筛「华东化纤」时整行保留,对侧装货客户仍在。
</p>
<div class="scheme-meta">
<span class="meta-chip pro">筛选不丢对侧</span>
<span class="meta-chip pro">列头可分别过滤</span>
<span class="meta-chip con">列变多,横向更挤</span>
</div>
<div class="filter-hint">
<span>模拟筛选</span>
<span class="tag">送货客户 ≈ 华东化纤</span>
<span>→ 整行保留,左侧装货客户「宜昌港务」仍可见</span>
</div>
<div class="table-wrap">
<table class="list">
<thead>
<tr>
<th>计划编号</th>
<th class="center">日期</th>
<th class="center">归档</th>
<th class="center">车牌</th>
<th>装货客户</th>
<th>装货地址 / 时间</th>
<th>送货客户</th>
<th>送货地址 / 时间</th>
<th>产品</th>
<th class="center">装货量</th>
<th class="center">送货量</th>
</tr>
</thead>
<tbody>
<tr>
<td class="merge-cell" rowspan="2"><a class="plan-link" href="#">JH260330-001</a></td>
<td class="merge-cell center" rowspan="2">03-30</td>
<td class="merge-cell center" rowspan="2"><span class="status-tag">已归档</span></td>
<td class="merge-cell center" rowspan="2">鄂E·A1234</td>
<td>宜昌港务<span class="internal-tag">内部</span></td>
<td class="addr">港区 3 号仓<br>08:00</td>
<td>华东化纤</td>
<td class="addr">苏州工业园…<br>14:00</td>
<td><div class="product-line">尿素 · 50kg</div></td>
<td class="center qty">32</td>
<td class="center qty">20</td>
</tr>
<tr>
<td>宜昌港务<span class="internal-tag">内部</span></td>
<td class="addr">港区 3 号仓<br>08:00</td>
<td>南通农资</td>
<td class="addr">南通开发区…<br>16:30</td>
<td><div class="product-line">复合肥 · 25kg</div></td>
<td class="center qty">18</td>
<td class="center qty">18</td>
</tr>
<tr class="plan-alt">
<td><a class="plan-link" href="#">JH260330-002</a></td>
<td class="center">03-30</td>
<td class="center"><span class="status-tag draft">草稿</span></td>
<td class="center">鄂E·B5678</td>
<td>枝江化肥厂</td>
<td class="addr">一号库<br>09:30</td>
<td>武汉商贸</td>
<td class="addr">汉阳物流园…<br>15:00</td>
<td><div class="product-line">尿素 · 50kg</div></td>
<td class="center qty">40</td>
<td class="center qty">40</td>
</tr>
</tbody>
</table>
</div>
<div class="legend">
<h3>方案要点</h3>
<ul>
<li>同一计划多送货 → 多行;计划编号等计划级字段仍可跨行合并。</li>
<li>装货客户在多行会重复出现(同一装货点),这是配对模式的正常表现。</li>
<li>与归档 Excel 导出的「装货×送货」视角一致,利于列表/导出心智统一。</li>
</ul>
</div>
</section>
<!-- ========== C 叠放 ========== -->
<section class="scheme-panel" id="scheme-c" role="tabpanel">
<p class="scheme-desc">
<strong>方案 C:</strong>仍是「一行一装一送」,但客户 / 地址仍各用<strong>一列</strong>,
单元格内<strong>上装货、下送货</strong>叠放,用绿/蓝底区分。列数接近现状,横向更省。
</p>
<div class="scheme-meta">
<span class="meta-chip pro">筛选不丢对侧</span>
<span class="meta-chip pro">列数少,改动面相对小</span>
<span class="meta-chip con">无法单独按「装货客户」「送货客户」列头过滤</span>
<span class="meta-chip con">行高变高,一屏行数变少</span>
</div>
<div class="filter-hint">
<span>模拟筛选</span>
<span class="tag">客户 ≈ 华东化纤</span>
<span>→ 匹配送货侧即可保留整行;单元格内装货侧仍展示</span>
</div>
<div class="table-wrap">
<table class="list">
<thead>
<tr>
<th>计划编号</th>
<th class="center">日期</th>
<th class="center">归档</th>
<th class="center">车牌</th>
<th>客户(装 / 送)</th>
<th>地址 / 时间(装 / 送)</th>
<th>产品</th>
<th class="center">数量(装→送)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="merge-cell" rowspan="2"><a class="plan-link" href="#">JH260330-001</a></td>
<td class="merge-cell center" rowspan="2">03-30</td>
<td class="merge-cell center" rowspan="2"><span class="status-tag">已归档</span></td>
<td class="merge-cell center" rowspan="2">鄂E·A1234</td>
<td>
<div class="stack-cell">
<div class="stack-row load">
<span class="side-label load">装</span>
<div class="body"><div class="name">宜昌港务<span class="internal-tag">内部</span></div></div>
</div>
<div class="stack-row delivery">
<span class="side-label delivery">送</span>
<div class="body"><div class="name">华东化纤</div></div>
</div>
</div>
</td>
<td>
<div class="stack-cell">
<div class="stack-row load">
<div class="body">
<div class="name">港区 3 号仓</div>
<div class="sub">03-30 08:00</div>
</div>
</div>
<div class="stack-row delivery">
<div class="body">
<div class="name">苏州工业园…</div>
<div class="sub">03-30 14:00</div>
</div>
</div>
</div>
</td>
<td><div class="product-line">尿素 · 50kg</div></td>
<td class="center qty">32 → 20</td>
</tr>
<tr>
<td>
<div class="stack-cell">
<div class="stack-row load">
<span class="side-label load">装</span>
<div class="body"><div class="name">宜昌港务<span class="internal-tag">内部</span></div></div>
</div>
<div class="stack-row delivery">
<span class="side-label delivery">送</span>
<div class="body"><div class="name">南通农资</div></div>
</div>
</div>
</td>
<td>
<div class="stack-cell">
<div class="stack-row load">
<div class="body">
<div class="name">港区 3 号仓</div>
<div class="sub">03-30 08:00</div>
</div>
</div>
<div class="stack-row delivery">
<div class="body">
<div class="name">南通开发区…</div>
<div class="sub">03-30 16:30</div>
</div>
</div>
</div>
</td>
<td><div class="product-line">复合肥 · 25kg</div></td>
<td class="center qty">18 → 18</td>
</tr>
<tr class="plan-alt">
<td><a class="plan-link" href="#">JH260330-002</a></td>
<td class="center">03-30</td>
<td class="center"><span class="status-tag draft">草稿</span></td>
<td class="center">鄂E·B5678</td>
<td>
<div class="stack-cell">
<div class="stack-row load">
<span class="side-label load">装</span>
<div class="body"><div class="name">枝江化肥厂</div></div>
</div>
<div class="stack-row delivery">
<span class="side-label delivery">送</span>
<div class="body"><div class="name">武汉商贸</div></div>
</div>
</div>
</td>
<td>
<div class="stack-cell">
<div class="stack-row load">
<div class="body">
<div class="name">一号库</div>
<div class="sub">03-30 09:30</div>
</div>
</div>
<div class="stack-row delivery">
<div class="body">
<div class="name">汉阳物流园…</div>
<div class="sub">03-30 15:00</div>
</div>
</div>
</div>
</td>
<td><div class="product-line">尿素 · 50kg</div></td>
<td class="center qty">40 → 40</td>
</tr>
</tbody>
</table>
</div>
<div class="legend">
<h3>方案要点</h3>
<ul>
<li>适合希望「改列结构少、但一眼能看到装→送」的过渡方案。</li>
<li>合同列也可同样上下叠放;若合同很多,单元格会显得更挤。</li>
</ul>
</div>
</section>
<!-- ========== D 分组表头 ========== -->
<section class="scheme-panel" id="scheme-d" role="tabpanel">
<p class="scheme-desc">
<strong>方案 D:</strong>与 B 同为拆列,但用<strong>双层表头</strong>把「装货」「送货」收成两组,
视觉分区更强,适合列特别多时扫读。实现成本略高于 B(表头合并、列显隐要一起处理)。
</p>
<div class="scheme-meta">
<span class="meta-chip pro">筛选不丢对侧</span>
<span class="meta-chip pro">装/送分区最清晰</span>
<span class="meta-chip con">双层表头 + 列显隐更复杂</span>
<span class="meta-chip con">窄屏横向滚动压力大</span>
</div>
<div class="filter-hint">
<span>模拟筛选</span>
<span class="tag">送货 · 客户 ≈ 华东化纤</span>
<span>→ 与方案 B 相同:整行保留</span>
</div>
<div class="table-wrap">
<table class="list">
<thead>
<tr class="group-row">
<th rowspan="2">计划编号</th>
<th rowspan="2" class="center">日期</th>
<th rowspan="2" class="center">归档</th>
<th rowspan="2" class="center">车牌</th>
<th class="group-load" colspan="2">装货</th>
<th class="group-delivery" colspan="2">送货</th>
<th rowspan="2">产品</th>
<th rowspan="2" class="center">装货量</th>
<th rowspan="2" class="center">送货量</th>
</tr>
<tr class="subhead">
<th class="group-load">客户</th>
<th class="group-load">地址 / 时间</th>
<th class="group-delivery">客户</th>
<th class="group-delivery">地址 / 时间</th>
</tr>
</thead>
<tbody>
<tr>
<td class="merge-cell" rowspan="2"><a class="plan-link" href="#">JH260330-001</a></td>
<td class="merge-cell center" rowspan="2">03-30</td>
<td class="merge-cell center" rowspan="2"><span class="status-tag">已归档</span></td>
<td class="merge-cell center" rowspan="2">鄂E·A1234</td>
<td class="col-load">宜昌港务<span class="internal-tag">内部</span></td>
<td class="col-load addr">港区 3 号仓<br>08:00</td>
<td class="col-delivery">华东化纤</td>
<td class="col-delivery addr">苏州工业园…<br>14:00</td>
<td><div class="product-line">尿素 · 50kg</div></td>
<td class="center qty">32</td>
<td class="center qty">20</td>
</tr>
<tr>
<td class="col-load">宜昌港务<span class="internal-tag">内部</span></td>
<td class="col-load addr">港区 3 号仓<br>08:00</td>
<td class="col-delivery">南通农资</td>
<td class="col-delivery addr">南通开发区…<br>16:30</td>
<td><div class="product-line">复合肥 · 25kg</div></td>
<td class="center qty">18</td>
<td class="center qty">18</td>
</tr>
<tr class="plan-alt">
<td><a class="plan-link" href="#">JH260330-002</a></td>
<td class="center">03-30</td>
<td class="center"><span class="status-tag draft">草稿</span></td>
<td class="center">鄂E·B5678</td>
<td class="col-load">枝江化肥厂</td>
<td class="col-load addr">一号库<br>09:30</td>
<td class="col-delivery">武汉商贸</td>
<td class="col-delivery addr">汉阳物流园…<br>15:00</td>
<td><div class="product-line">尿素 · 50kg</div></td>
<td class="center qty">40</td>
<td class="center qty">40</td>
</tr>
</tbody>
</table>
</div>
<div class="legend">
<h3>和 B 的差别</h3>
<ul>
<li>数据行结构相同,主要是表头分组与底色分区。</li>
<li>若选 B,后续也可再升级成 D,不必一次到位。</li>
</ul>
</div>
</section>
</div>
<script>
(function () {
var tabs = document.querySelectorAll('.scheme-tab')
var panels = document.querySelectorAll('.scheme-panel')
tabs.forEach(function (tab) {
tab.addEventListener('click', function () {
var id = tab.getAttribute('data-scheme')
tabs.forEach(function (t) {
var on = t === tab
t.classList.toggle('active', on)
t.setAttribute('aria-selected', on ? 'true' : 'false')
})
panels.forEach(function (p) {
p.classList.toggle('active', p.id === 'scheme-' + id)
})
})
})
})()
</script>
</body>
</html>