563 lines
21 KiB
HTML
563 lines
21 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<title>运输计划 · 装/送结构重设计</title>
|
|
<style>
|
|
:root {
|
|
--load: #059669;
|
|
--delivery: #0284c7;
|
|
--text: #1e293b;
|
|
--muted: #64748b;
|
|
--border: #e2e8f0;
|
|
--page: #eef2f6;
|
|
--panel: #fff;
|
|
--primary: #10b981;
|
|
}
|
|
* { box-sizing: border-box; }
|
|
body {
|
|
margin: 0;
|
|
padding: 28px 20px 80px;
|
|
font-family: Inter, "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;
|
|
font-size: 14px;
|
|
color: var(--text);
|
|
background: var(--page);
|
|
}
|
|
h1 { margin: 0 0 6px; font-size: 20px; font-weight: 700; }
|
|
.lead { margin: 0 0 10px; max-width: 860px; color: var(--muted); font-size: 13.5px; line-height: 1.55; }
|
|
.shift {
|
|
margin: 0 0 22px; padding: 12px 14px; max-width: 860px;
|
|
border-radius: 8px; background: #ecfdf5; border: 1px solid #a7f3d0;
|
|
color: #065f46; font-size: 13px; line-height: 1.5;
|
|
}
|
|
|
|
.scheme {
|
|
margin-bottom: 22px;
|
|
background: var(--panel);
|
|
border: 1px solid var(--border);
|
|
border-radius: 12px;
|
|
overflow: hidden;
|
|
}
|
|
.scheme.is-rec { border-color: #6ee7b7; box-shadow: 0 0 0 1px #a7f3d0; }
|
|
.scheme__head {
|
|
display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
|
|
padding: 14px 16px; border-bottom: 1px solid var(--border);
|
|
background: #fafbfc;
|
|
}
|
|
.scheme__title { margin: 0; font-size: 15px; font-weight: 700; }
|
|
.scheme__why { margin: 4px 0 0; font-size: 12.5px; color: var(--muted); line-height: 1.45; }
|
|
.badge {
|
|
flex-shrink: 0; padding: 2px 9px; border-radius: 999px;
|
|
font-size: 11px; font-weight: 600;
|
|
}
|
|
.badge--rec { color: #065f46; background: #ecfdf5; border: 1px solid #a7f3d0; }
|
|
.badge--alt { color: #475569; background: #f8fafc; border: 1px solid #e2e8f0; }
|
|
.scheme__body { padding: 16px; }
|
|
.scheme__note { margin: 12px 0 0; font-size: 12.5px; color: var(--muted); line-height: 1.5; }
|
|
|
|
table.t {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
font-size: 13px;
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
overflow: hidden;
|
|
}
|
|
table.t th, table.t td {
|
|
padding: 8px 10px;
|
|
border-bottom: 1px solid var(--border);
|
|
border-right: 1px solid var(--border);
|
|
vertical-align: middle;
|
|
}
|
|
table.t th:last-child, table.t td:last-child { border-right: none; }
|
|
table.t tr:last-child td { border-bottom: none; }
|
|
table.t thead th {
|
|
background: #f8fafc;
|
|
color: var(--muted);
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
text-align: center;
|
|
white-space: nowrap;
|
|
}
|
|
table.t .left { text-align: left; }
|
|
table.t .num { text-align: center; font-variant-numeric: tabular-nums; font-weight: 600; }
|
|
table.t .muted { color: var(--muted); font-weight: 500; }
|
|
.addr { font-weight: 600; line-height: 1.4; }
|
|
.time { margin-top: 2px; font-size: 12px; color: var(--muted); font-weight: 400; }
|
|
|
|
/* S1 二级表头 */
|
|
.s1 thead .group { background: #f1f5f9; color: var(--text); font-weight: 700; }
|
|
.s1 thead .sub-load { color: var(--load); }
|
|
.s1 thead .sub-delivery { color: var(--delivery); }
|
|
.s1 tbody td { background: #fff; }
|
|
|
|
/* S2 两行 */
|
|
.s2 .kind {
|
|
width: 36px; text-align: center; font-size: 11px; font-weight: 800;
|
|
}
|
|
.s2 .kind--load { color: var(--load); }
|
|
.s2 .kind--delivery { color: var(--delivery); }
|
|
.s2 tr.load-row td { background: #fff; }
|
|
.s2 tr.delivery-row td { background: #fafbfc; }
|
|
.s2 tr.pair-end td { border-bottom: 2px solid #94a3b8; }
|
|
|
|
/* S3 视图切换 */
|
|
.tabs {
|
|
display: inline-flex; gap: 0; margin-bottom: 10px;
|
|
border: 1px solid var(--border); border-radius: 8px; overflow: hidden;
|
|
}
|
|
.tabs button {
|
|
appearance: none; border: none; background: #fff;
|
|
padding: 7px 14px; font-size: 13px; color: var(--muted); cursor: pointer;
|
|
font-family: inherit;
|
|
}
|
|
.tabs button + button { border-left: 1px solid var(--border); }
|
|
.tabs button.active {
|
|
background: var(--primary); color: #fff; font-weight: 600;
|
|
}
|
|
.view-panel { display: none; }
|
|
.view-panel.active { display: block; }
|
|
|
|
/* S4 左侧类型轨(整行共享) */
|
|
.s4 .rail-cell {
|
|
width: 28px; padding: 0 !important; vertical-align: stretch !important;
|
|
}
|
|
.s4 .rail {
|
|
display: flex; flex-direction: column; height: 100%; min-height: 64px;
|
|
}
|
|
.s4 .rail > span {
|
|
flex: 1; display: flex; align-items: center; justify-content: center;
|
|
writing-mode: vertical-rl; text-orientation: mixed;
|
|
font-size: 11px; font-weight: 800; letter-spacing: 0.12em;
|
|
color: #fff;
|
|
}
|
|
.s4 .rail > span.load { background: var(--load); }
|
|
.s4 .rail > span.delivery { background: var(--delivery); }
|
|
.s4 .stack { display: flex; flex-direction: column; gap: 0; }
|
|
.s4 .stack > div { padding: 5px 0; }
|
|
.s4 .stack > div + div {
|
|
border-top: 1px dashed var(--border); margin-top: 5px; padding-top: 5px;
|
|
}
|
|
|
|
/* S5 卡片对照 */
|
|
.cards { display: grid; grid-template-columns: 1fr auto 1fr; gap: 10px; align-items: stretch; }
|
|
.stop-card {
|
|
border: 1px solid var(--border); border-radius: 10px; padding: 12px 14px;
|
|
background: #fff;
|
|
}
|
|
.stop-card--load { border-top: 3px solid var(--load); }
|
|
.stop-card--delivery { border-top: 3px solid var(--delivery); }
|
|
.stop-card__role {
|
|
font-size: 11px; font-weight: 700; letter-spacing: 0.06em;
|
|
margin-bottom: 8px;
|
|
}
|
|
.stop-card--load .stop-card__role { color: var(--load); }
|
|
.stop-card--delivery .stop-card__role { color: var(--delivery); }
|
|
.stop-card__addr { font-weight: 600; margin-bottom: 4px; }
|
|
.stop-card__meta { font-size: 12px; color: var(--muted); }
|
|
.stop-card__kvs {
|
|
display: grid; grid-template-columns: 1fr 1fr; gap: 6px 12px;
|
|
margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border);
|
|
font-size: 12px;
|
|
}
|
|
.stop-card__kvs span { color: var(--muted); }
|
|
.stop-card__kvs b { display: block; margin-top: 2px; font-size: 14px; color: var(--text); font-variant-numeric: tabular-nums; }
|
|
.cards__arrow {
|
|
display: flex; align-items: center; justify-content: center;
|
|
color: #94a3b8; font-size: 18px;
|
|
}
|
|
.plan-meta {
|
|
margin-bottom: 10px; font-size: 12px; color: var(--muted);
|
|
}
|
|
.plan-meta strong { color: var(--text); }
|
|
|
|
.footer-pick {
|
|
margin-top: 8px; padding: 16px 18px; max-width: 860px;
|
|
background: #fff; border: 1px solid var(--border); border-radius: 10px;
|
|
}
|
|
.footer-pick h2 { margin: 0 0 8px; font-size: 14px; }
|
|
.footer-pick ol { margin: 0; padding-left: 18px; color: var(--muted); font-size: 13px; }
|
|
.footer-pick li { margin: 6px 0; }
|
|
.footer-pick strong { color: var(--text); }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>装 / 送 · 结构重设计(不再靠格子里贴标记)</h1>
|
|
<p class="lead">
|
|
之前方案的问题:无论汉字、色条还是字色,都是<strong>在每个单元格里重复表达一次</strong>,列一多就吵。
|
|
这轮改从<strong>表格结构</strong>下手——让「装/送」只出现在表头、首列或视图切换里,正文格子尽量只放数据。
|
|
</p>
|
|
<p class="shift">
|
|
设计原则:标记出现次数 ≈ 1(表头 / 首列 / 工具栏),而不是 ≈ 列数 × 行数。
|
|
</p>
|
|
|
|
<!-- S1 -->
|
|
<section class="scheme is-rec">
|
|
<div class="scheme__head">
|
|
<div>
|
|
<h2 class="scheme__title">S1 · 二级表头拆列</h2>
|
|
<p class="scheme__why">「计划数量」拆成子列「装 / 送」,单元格里只有数字,汉字只出现在表头各一次。</p>
|
|
</div>
|
|
<span class="badge badge--rec">列表推荐</span>
|
|
</div>
|
|
<div class="scheme__body">
|
|
<table class="t s1">
|
|
<thead>
|
|
<tr>
|
|
<th class="left" rowspan="2">装货地址</th>
|
|
<th class="left" rowspan="2">送货地址</th>
|
|
<th class="group" colspan="2">计划数量</th>
|
|
<th class="group" colspan="2">单价</th>
|
|
<th class="group" colspan="2">金额</th>
|
|
</tr>
|
|
<tr>
|
|
<th class="sub-load">装</th>
|
|
<th class="sub-delivery">送</th>
|
|
<th class="sub-load">装</th>
|
|
<th class="sub-delivery">送</th>
|
|
<th class="sub-load">装</th>
|
|
<th class="sub-delivery">送</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td class="left">
|
|
<div class="addr">宜昌西陵化工园 A12</div>
|
|
<div class="time">09-16 08:30</div>
|
|
</td>
|
|
<td class="left">
|
|
<div class="addr">武汉东西湖物流大道 88</div>
|
|
<div class="time">09-16 16:00</div>
|
|
</td>
|
|
<td class="num">0.01</td>
|
|
<td class="num">0.01</td>
|
|
<td class="num">10</td>
|
|
<td class="num muted">—</td>
|
|
<td class="num">33</td>
|
|
<td class="num muted">—</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="left">
|
|
<div class="addr">荆州某仓库</div>
|
|
<div class="time">09-17 09:00</div>
|
|
</td>
|
|
<td class="left">
|
|
<div class="addr">长沙物流园 B3</div>
|
|
<div class="time">09-17 18:00</div>
|
|
</td>
|
|
<td class="num">12</td>
|
|
<td class="num">12</td>
|
|
<td class="num">8.5</td>
|
|
<td class="num">9.0</td>
|
|
<td class="num">102</td>
|
|
<td class="num">108</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<p class="scheme__note">
|
|
正文零「装/送」重复。代价:列变多(可用列设置隐藏次要子列)。地址也拆成两列,上下对齐更清晰。
|
|
Element Plus 原生支持多级表头,和现有列设置能力兼容。
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- S2 -->
|
|
<section class="scheme is-rec">
|
|
<div class="scheme__head">
|
|
<div>
|
|
<h2 class="scheme__title">S2 · 拆成两行(装一行、送一行)</h2>
|
|
<p class="scheme__why">一条配对变成上下两行;「装/送」只在最左类型列出现一次,其余列全是普通单元格。</p>
|
|
</div>
|
|
<span class="badge badge--rec">列表推荐</span>
|
|
</div>
|
|
<div class="scheme__body">
|
|
<table class="t s2">
|
|
<thead>
|
|
<tr>
|
|
<th></th>
|
|
<th class="left">地址 / 时间</th>
|
|
<th>计划数量</th>
|
|
<th>实际数量</th>
|
|
<th>单价</th>
|
|
<th>金额</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr class="load-row">
|
|
<td class="kind kind--load">装</td>
|
|
<td class="left">
|
|
<div class="addr">宜昌西陵化工园 A12</div>
|
|
<div class="time">09-16 08:30</div>
|
|
</td>
|
|
<td class="num">0.01</td>
|
|
<td class="num">0.01</td>
|
|
<td class="num">10</td>
|
|
<td class="num">33</td>
|
|
</tr>
|
|
<tr class="delivery-row pair-end">
|
|
<td class="kind kind--delivery">送</td>
|
|
<td class="left">
|
|
<div class="addr">武汉东西湖物流大道 88</div>
|
|
<div class="time">09-16 16:00</div>
|
|
</td>
|
|
<td class="num">0.01</td>
|
|
<td class="num">0.01</td>
|
|
<td class="num muted">—</td>
|
|
<td class="num muted">—</td>
|
|
</tr>
|
|
<tr class="load-row">
|
|
<td class="kind kind--load">装</td>
|
|
<td class="left">
|
|
<div class="addr">荆州某仓库</div>
|
|
<div class="time">09-17 09:00</div>
|
|
</td>
|
|
<td class="num">12</td>
|
|
<td class="num">12</td>
|
|
<td class="num">8.5</td>
|
|
<td class="num">102</td>
|
|
</tr>
|
|
<tr class="delivery-row pair-end">
|
|
<td class="kind kind--delivery">送</td>
|
|
<td class="left">
|
|
<div class="addr">长沙物流园 B3</div>
|
|
<div class="time">09-17 18:00</div>
|
|
</td>
|
|
<td class="num">12</td>
|
|
<td class="num">11.8</td>
|
|
<td class="num">9.0</td>
|
|
<td class="num">106.2</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<p class="scheme__note">
|
|
这是物流/仓储系统里最常见的读法:横扫一行全是「装」的数据,再扫下一行全是「送」。
|
|
合并单元格(车牌、司机等计划级字段)可跨两行合并。改动比换皮肤大,但噪音下降最彻底。
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- S3 -->
|
|
<section class="scheme">
|
|
<div class="scheme__head">
|
|
<div>
|
|
<h2 class="scheme__title">S3 · 视图切换(一次只看一层)</h2>
|
|
<p class="scheme__why">默认看「装货」或「送货」单层列表;需要对照时再进对照模式。</p>
|
|
</div>
|
|
<span class="badge badge--alt">备选</span>
|
|
</div>
|
|
<div class="scheme__body">
|
|
<div class="tabs" id="s3-tabs">
|
|
<button type="button" class="active" data-view="load">装货</button>
|
|
<button type="button" data-view="delivery">送货</button>
|
|
<button type="button" data-view="both">对照</button>
|
|
</div>
|
|
<div class="view-panel active" data-view="load">
|
|
<table class="t">
|
|
<thead>
|
|
<tr>
|
|
<th class="left">装货地址</th>
|
|
<th>计划数量</th>
|
|
<th>单价</th>
|
|
<th>金额</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td class="left">
|
|
<div class="addr">宜昌西陵化工园 A12</div>
|
|
<div class="time">09-16 08:30</div>
|
|
</td>
|
|
<td class="num">0.01</td>
|
|
<td class="num">10</td>
|
|
<td class="num">33</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="view-panel" data-view="delivery">
|
|
<table class="t">
|
|
<thead>
|
|
<tr>
|
|
<th class="left">送货地址</th>
|
|
<th>计划数量</th>
|
|
<th>单价</th>
|
|
<th>金额</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td class="left">
|
|
<div class="addr">武汉东西湖物流大道 88</div>
|
|
<div class="time">09-16 16:00</div>
|
|
</td>
|
|
<td class="num">0.01</td>
|
|
<td class="num muted">—</td>
|
|
<td class="num muted">—</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="view-panel" data-view="both">
|
|
<p style="margin:0 0 8px;font-size:12px;color:var(--muted)">对照模式可用 S1 或 S2,此处示意用 S1 子列。</p>
|
|
<table class="t s1">
|
|
<thead>
|
|
<tr>
|
|
<th class="left" rowspan="2">装货地址</th>
|
|
<th class="left" rowspan="2">送货地址</th>
|
|
<th class="group" colspan="2">计划数量</th>
|
|
</tr>
|
|
<tr>
|
|
<th class="sub-load">装</th>
|
|
<th class="sub-delivery">送</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td class="left"><div class="addr">宜昌西陵化工园 A12</div></td>
|
|
<td class="left"><div class="addr">武汉东西湖物流大道 88</div></td>
|
|
<td class="num">0.01</td>
|
|
<td class="num">0.01</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<p class="scheme__note">日常调度若多数时间只关心一侧(如只盯装货),噪音为零。需要装送对齐核对时切到对照。</p>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- S4 -->
|
|
<section class="scheme">
|
|
<div class="scheme__head">
|
|
<div>
|
|
<h2 class="scheme__title">S4 · 整行共享左侧类型轨</h2>
|
|
<p class="scheme__why">保留「一格里上下叠」的数据结构,但类型只在表格最左侧出现一次(半格装、半格送)。</p>
|
|
</div>
|
|
<span class="badge badge--alt">小改动</span>
|
|
</div>
|
|
<div class="scheme__body">
|
|
<table class="t s4">
|
|
<thead>
|
|
<tr>
|
|
<th style="width:28px"></th>
|
|
<th class="left">地址</th>
|
|
<th>计划数量</th>
|
|
<th>单价</th>
|
|
<th>金额</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td class="rail-cell">
|
|
<div class="rail">
|
|
<span class="load">装</span>
|
|
<span class="delivery">送</span>
|
|
</div>
|
|
</td>
|
|
<td class="left">
|
|
<div class="stack">
|
|
<div>
|
|
<div class="addr">宜昌西陵化工园 A12</div>
|
|
<div class="time">09-16 08:30</div>
|
|
</div>
|
|
<div>
|
|
<div class="addr">武汉东西湖物流大道 88</div>
|
|
<div class="time">09-16 16:00</div>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div class="stack">
|
|
<div class="num">0.01</div>
|
|
<div class="num">0.01</div>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div class="stack">
|
|
<div class="num">10</div>
|
|
<div class="num muted">—</div>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div class="stack">
|
|
<div class="num">33</div>
|
|
<div class="num muted">—</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<p class="scheme__note">
|
|
对现有「配对叠放」改动最小:删掉每个 cell 里的 label,最左侧加一列类型轨。
|
|
数量列变干净,但行内仍要上下对齐扫读。
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- S5 -->
|
|
<section class="scheme">
|
|
<div class="scheme__head">
|
|
<div>
|
|
<h2 class="scheme__title">S5 · 左装右送卡片对照</h2>
|
|
<p class="scheme__why">不做密表叠字;每条计划一张对照卡,装/送各写一次角色名。</p>
|
|
</div>
|
|
<span class="badge badge--alt">备选</span>
|
|
</div>
|
|
<div class="scheme__body">
|
|
<div class="plan-meta">计划号 <strong>JH20260916001</strong> · 车牌 鄂A·12X34 · 司机 张三</div>
|
|
<div class="cards">
|
|
<div class="stop-card stop-card--load">
|
|
<div class="stop-card__role">装货</div>
|
|
<div class="stop-card__addr">宜昌西陵化工园 A12</div>
|
|
<div class="stop-card__meta">09-16 08:30</div>
|
|
<div class="stop-card__kvs">
|
|
<div><span>计划数量</span><b>0.01</b></div>
|
|
<div><span>单价</span><b>10</b></div>
|
|
<div><span>入库</span><b>0.01</b></div>
|
|
<div><span>金额</span><b>33</b></div>
|
|
</div>
|
|
</div>
|
|
<div class="cards__arrow">→</div>
|
|
<div class="stop-card stop-card--delivery">
|
|
<div class="stop-card__role">送货</div>
|
|
<div class="stop-card__addr">武汉东西湖物流大道 88</div>
|
|
<div class="stop-card__meta">09-16 16:00</div>
|
|
<div class="stop-card__kvs">
|
|
<div><span>计划数量</span><b>0.01</b></div>
|
|
<div><span>单价</span><b>—</b></div>
|
|
<div><span>出库</span><b>0.01</b></div>
|
|
<div><span>金额</span><b>—</b></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<p class="scheme__note">适合详情/移动端/低密度审核。桌面高密度调度列表通常仍应以 S1/S2 为主。</p>
|
|
</div>
|
|
</section>
|
|
|
|
<div class="footer-pick">
|
|
<h2>建议</h2>
|
|
<ol>
|
|
<li><strong>S1 二级表头</strong>:继续「一行一条配对」,但数量类字段左右对照,最适合你截图里的数量/单价/金额列。</li>
|
|
<li><strong>S2 拆两行</strong>:横扫读法最直觉,计划级字段用行合并;适合愿意改列表数据模型的情况。</li>
|
|
<li><strong>S4</strong>:想最小改动、先去掉满屏「装/送」时的过渡方案。</li>
|
|
</ol>
|
|
<p style="margin:12px 0 0;font-size:13px;color:#64748b">回复 S1 / S2 / S4(或组合,如「数量列用 S1,地址先保持叠放」),再落到正式页面。</p>
|
|
</div>
|
|
|
|
<script>
|
|
const tabs = document.getElementById('s3-tabs')
|
|
if (tabs) {
|
|
tabs.addEventListener('click', (e) => {
|
|
const btn = e.target.closest('button[data-view]')
|
|
if (!btn) return
|
|
const view = btn.getAttribute('data-view')
|
|
tabs.querySelectorAll('button').forEach((b) => b.classList.toggle('active', b === btn))
|
|
document.querySelectorAll('.view-panel').forEach((p) => {
|
|
p.classList.toggle('active', p.getAttribute('data-view') === view)
|
|
})
|
|
})
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|