|
|
@@ -0,0 +1,657 @@
|
|
|
+<!DOCTYPE html>
|
|
|
+<html lang="zh-CN">
|
|
|
+<head>
|
|
|
+ <meta charset="UTF-8" />
|
|
|
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover" />
|
|
|
+ <title>司机链接 · 运输记录 Demo</title>
|
|
|
+ <style>
|
|
|
+ :root {
|
|
|
+ --green: #059669;
|
|
|
+ --green-deep: #047857;
|
|
|
+ --green-soft: #ecfdf5;
|
|
|
+ --text: #1e293b;
|
|
|
+ --muted: #64748b;
|
|
|
+ --line: #e2e8f0;
|
|
|
+ --bg: #f1f5f9;
|
|
|
+ --warn: #d97706;
|
|
|
+ --danger: #dc2626;
|
|
|
+ --card: #fff;
|
|
|
+ --radius: 12px;
|
|
|
+ --safe-bottom: env(safe-area-inset-bottom, 0px);
|
|
|
+ }
|
|
|
+ * { box-sizing: border-box; }
|
|
|
+ body {
|
|
|
+ margin: 0;
|
|
|
+ font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Segoe UI", sans-serif;
|
|
|
+ background: #0f172a;
|
|
|
+ color: var(--text);
|
|
|
+ min-height: 100vh;
|
|
|
+ }
|
|
|
+ .stage {
|
|
|
+ max-width: 1100px;
|
|
|
+ margin: 0 auto;
|
|
|
+ padding: 24px 16px 48px;
|
|
|
+ }
|
|
|
+ .stage-head {
|
|
|
+ color: #e2e8f0;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ }
|
|
|
+ .stage-head h1 {
|
|
|
+ margin: 0 0 8px;
|
|
|
+ font-size: 22px;
|
|
|
+ font-weight: 700;
|
|
|
+ }
|
|
|
+ .stage-head p {
|
|
|
+ margin: 0;
|
|
|
+ color: #94a3b8;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 1.6;
|
|
|
+ }
|
|
|
+ .phones {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
|
|
+ gap: 20px;
|
|
|
+ }
|
|
|
+ .phone-wrap {
|
|
|
+ background: #1e293b;
|
|
|
+ border-radius: 20px;
|
|
|
+ padding: 12px;
|
|
|
+ border: 1px solid #334155;
|
|
|
+ }
|
|
|
+ .phone-label {
|
|
|
+ color: #cbd5e1;
|
|
|
+ font-size: 13px;
|
|
|
+ font-weight: 600;
|
|
|
+ margin: 0 0 10px 4px;
|
|
|
+ }
|
|
|
+ .phone {
|
|
|
+ width: 100%;
|
|
|
+ max-width: 390px;
|
|
|
+ margin: 0 auto;
|
|
|
+ background: var(--bg);
|
|
|
+ border-radius: 18px;
|
|
|
+ overflow: hidden;
|
|
|
+ min-height: 720px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ box-shadow: 0 20px 40px rgba(0,0,0,.35);
|
|
|
+ position: relative;
|
|
|
+ }
|
|
|
+ .nav {
|
|
|
+ background: var(--green);
|
|
|
+ color: #fff;
|
|
|
+ height: 48px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 600;
|
|
|
+ position: relative;
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+ .nav .back {
|
|
|
+ position: absolute;
|
|
|
+ left: 12px;
|
|
|
+ top: 50%;
|
|
|
+ transform: translateY(-50%);
|
|
|
+ background: transparent;
|
|
|
+ border: 0;
|
|
|
+ color: #fff;
|
|
|
+ font-size: 14px;
|
|
|
+ cursor: pointer;
|
|
|
+ padding: 8px;
|
|
|
+ }
|
|
|
+ .scroll {
|
|
|
+ flex: 1;
|
|
|
+ overflow: auto;
|
|
|
+ padding: 12px 12px 96px;
|
|
|
+ }
|
|
|
+ .scroll.no-footer-pad { padding-bottom: 12px; }
|
|
|
+ .card {
|
|
|
+ background: var(--card);
|
|
|
+ border-radius: var(--radius);
|
|
|
+ margin-bottom: 12px;
|
|
|
+ overflow: hidden;
|
|
|
+ border: 1px solid #eef2f7;
|
|
|
+ }
|
|
|
+ .card-title {
|
|
|
+ padding: 10px 14px 0;
|
|
|
+ font-size: 13px;
|
|
|
+ color: var(--muted);
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+ .row {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ gap: 12px;
|
|
|
+ padding: 12px 14px;
|
|
|
+ border-bottom: 1px solid #f1f5f9;
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+ .row:last-child { border-bottom: 0; }
|
|
|
+ .row .k { color: var(--muted); flex-shrink: 0; }
|
|
|
+ .row .v { color: var(--text); text-align: right; word-break: break-all; }
|
|
|
+ .empty {
|
|
|
+ padding: 64px 24px;
|
|
|
+ text-align: center;
|
|
|
+ color: var(--muted);
|
|
|
+ }
|
|
|
+ .empty .icon {
|
|
|
+ width: 64px;
|
|
|
+ height: 64px;
|
|
|
+ margin: 0 auto 16px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: #e2e8f0;
|
|
|
+ display: grid;
|
|
|
+ place-items: center;
|
|
|
+ font-size: 28px;
|
|
|
+ color: #94a3b8;
|
|
|
+ }
|
|
|
+ .empty .title {
|
|
|
+ font-size: 15px;
|
|
|
+ color: #475569;
|
|
|
+ margin-bottom: 6px;
|
|
|
+ }
|
|
|
+ .footer {
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ padding: 10px 12px calc(10px + var(--safe-bottom));
|
|
|
+ background: rgba(255,255,255,.96);
|
|
|
+ border-top: 1px solid var(--line);
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 8px;
|
|
|
+ backdrop-filter: blur(8px);
|
|
|
+ }
|
|
|
+ .btn {
|
|
|
+ height: 44px;
|
|
|
+ border-radius: 999px;
|
|
|
+ border: 0;
|
|
|
+ font-size: 15px;
|
|
|
+ font-weight: 600;
|
|
|
+ cursor: pointer;
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ gap: 6px;
|
|
|
+ }
|
|
|
+ .btn-primary {
|
|
|
+ background: var(--green);
|
|
|
+ color: #fff;
|
|
|
+ }
|
|
|
+ .btn-primary:active { background: var(--green-deep); }
|
|
|
+ .btn-ghost {
|
|
|
+ background: #fff;
|
|
|
+ color: var(--green);
|
|
|
+ border: 1px solid #a7f3d0;
|
|
|
+ }
|
|
|
+ .btn-ghost:active { background: var(--green-soft); }
|
|
|
+ .btn-row {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: 1fr 1fr;
|
|
|
+ gap: 8px;
|
|
|
+ }
|
|
|
+ .filters {
|
|
|
+ background: var(--card);
|
|
|
+ border-radius: var(--radius);
|
|
|
+ padding: 12px;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ border: 1px solid #eef2f7;
|
|
|
+ }
|
|
|
+ .filter-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ }
|
|
|
+ .filter-row:last-child { margin-bottom: 0; }
|
|
|
+ .chip {
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 6px;
|
|
|
+ height: 32px;
|
|
|
+ padding: 0 12px;
|
|
|
+ border-radius: 999px;
|
|
|
+ border: 1px solid var(--line);
|
|
|
+ background: #fff;
|
|
|
+ font-size: 13px;
|
|
|
+ color: var(--text);
|
|
|
+ cursor: pointer;
|
|
|
+ user-select: none;
|
|
|
+ }
|
|
|
+ .chip.on {
|
|
|
+ background: var(--green-soft);
|
|
|
+ border-color: #6ee7b7;
|
|
|
+ color: var(--green-deep);
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+ .chip input { display: none; }
|
|
|
+ .date-inputs {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: 1fr auto 1fr;
|
|
|
+ gap: 8px;
|
|
|
+ align-items: center;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ .date-inputs input {
|
|
|
+ height: 36px;
|
|
|
+ border: 1px solid var(--line);
|
|
|
+ border-radius: 8px;
|
|
|
+ padding: 0 10px;
|
|
|
+ font-size: 13px;
|
|
|
+ color: var(--text);
|
|
|
+ background: #fff;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ .date-inputs span { color: var(--muted); font-size: 12px; }
|
|
|
+ .hint {
|
|
|
+ font-size: 12px;
|
|
|
+ color: var(--muted);
|
|
|
+ margin-top: 8px;
|
|
|
+ }
|
|
|
+ .record {
|
|
|
+ background: var(--card);
|
|
|
+ border-radius: var(--radius);
|
|
|
+ border: 1px solid #eef2f7;
|
|
|
+ padding: 14px;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: border-color .15s, box-shadow .15s;
|
|
|
+ }
|
|
|
+ .record:active, .record:hover {
|
|
|
+ border-color: #6ee7b7;
|
|
|
+ box-shadow: 0 0 0 3px rgba(16,185,129,.12);
|
|
|
+ }
|
|
|
+ .record-top {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ gap: 8px;
|
|
|
+ align-items: flex-start;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ }
|
|
|
+ .record-no {
|
|
|
+ font-size: 15px;
|
|
|
+ font-weight: 700;
|
|
|
+ }
|
|
|
+ .tag {
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ height: 22px;
|
|
|
+ padding: 0 8px;
|
|
|
+ border-radius: 6px;
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #fff;
|
|
|
+ flex-shrink: 0;
|
|
|
+ }
|
|
|
+ .tag.ok { background: var(--green); }
|
|
|
+ .tag.arch { background: #64748b; }
|
|
|
+ .tag.void { background: var(--danger); }
|
|
|
+ .tag.warn { background: var(--warn); }
|
|
|
+ .record-meta {
|
|
|
+ font-size: 13px;
|
|
|
+ color: var(--muted);
|
|
|
+ line-height: 1.55;
|
|
|
+ }
|
|
|
+ .record-meta strong { color: var(--text); font-weight: 500; }
|
|
|
+ .mini-tabs {
|
|
|
+ display: flex;
|
|
|
+ gap: 8px;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ }
|
|
|
+ .mini-tabs button {
|
|
|
+ border: 1px solid #334155;
|
|
|
+ background: #0f172a;
|
|
|
+ color: #94a3b8;
|
|
|
+ border-radius: 999px;
|
|
|
+ padding: 8px 12px;
|
|
|
+ font-size: 12px;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ .mini-tabs button.active {
|
|
|
+ background: var(--green);
|
|
|
+ border-color: var(--green);
|
|
|
+ color: #fff;
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+ .note {
|
|
|
+ margin-top: 18px;
|
|
|
+ padding: 14px 16px;
|
|
|
+ background: #1e293b;
|
|
|
+ border: 1px solid #334155;
|
|
|
+ border-radius: 12px;
|
|
|
+ color: #cbd5e1;
|
|
|
+ font-size: 13px;
|
|
|
+ line-height: 1.7;
|
|
|
+ }
|
|
|
+ .note strong { color: #f8fafc; }
|
|
|
+ .screen { display: none; flex: 1; flex-direction: column; min-height: 0; }
|
|
|
+ .screen.active { display: flex; }
|
|
|
+ .product {
|
|
|
+ padding: 12px 14px;
|
|
|
+ border-top: 1px solid #f1f5f9;
|
|
|
+ }
|
|
|
+ .product-name { font-weight: 600; margin-bottom: 6px; }
|
|
|
+ .product-meta { font-size: 13px; color: var(--muted); }
|
|
|
+ </style>
|
|
|
+</head>
|
|
|
+<body>
|
|
|
+ <div class="stage">
|
|
|
+ <div class="stage-head">
|
|
|
+ <h1>司机链接 ·「运输记录」交互 Demo</h1>
|
|
|
+ <p>
|
|
|
+ 列表默认<strong>今天</strong>。筛选为:单日日期框 +「今天 / 明天 / 后天」快捷按钮。
|
|
|
+ 命中:取货日或送货日等于所选日。按<strong>主车车牌</strong>聚合。
|
|
|
+ </p>
|
|
|
+ <div class="mini-tabs" id="jumpTabs">
|
|
|
+ <button type="button" class="active" data-jump="A">A · 正常详情</button>
|
|
|
+ <button type="button" data-jump="B">B · 已归档详情</button>
|
|
|
+ <button type="button" data-jump="C">C · 运输记录列表</button>
|
|
|
+ <button type="button" data-jump="D">D · 作废详情</button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="phones">
|
|
|
+ <!-- Phone interactive -->
|
|
|
+ <div class="phone-wrap">
|
|
|
+ <div class="phone-label">可交互 Demo(点底部按钮 / 点记录)</div>
|
|
|
+ <div class="phone" id="phone">
|
|
|
+ <!-- Screen: active detail -->
|
|
|
+ <div class="screen active" data-screen="detail-active">
|
|
|
+ <div class="nav">运输计划</div>
|
|
|
+ <div class="scroll">
|
|
|
+ <div class="card">
|
|
|
+ <div class="row"><span class="k">计划编号</span><span class="v">YS20260821001</span></div>
|
|
|
+ <div class="row"><span class="k">计划日期</span><span class="v">2026-08-21</span></div>
|
|
|
+ <div class="row"><span class="k">车牌</span><span class="v">苏A·D12345</span></div>
|
|
|
+ <div class="row"><span class="k">司机</span><span class="v">张师傅</span></div>
|
|
|
+ </div>
|
|
|
+ <div class="card">
|
|
|
+ <div class="card-title">取货信息</div>
|
|
|
+ <div class="row"><span class="k">取货地址</span><span class="v">南京市江宁区××仓库</span></div>
|
|
|
+ <div class="row"><span class="k">取货时间</span><span class="v">2026-08-21 09:00</span></div>
|
|
|
+ </div>
|
|
|
+ <div class="card">
|
|
|
+ <div class="card-title">产品回传数量</div>
|
|
|
+ <div class="product">
|
|
|
+ <div class="product-name">硫酸</div>
|
|
|
+ <div class="product-meta">计划 28 吨 · 实际待填</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="footer">
|
|
|
+ <div class="btn-row">
|
|
|
+ <button class="btn btn-ghost" type="button" data-go="list">运输记录</button>
|
|
|
+ <button class="btn btn-primary" type="button">保存回执</button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- Screen: archived detail (from link or list) -->
|
|
|
+ <div class="screen" data-screen="detail-archived">
|
|
|
+ <div class="nav">运输计划</div>
|
|
|
+ <div class="scroll no-footer-pad">
|
|
|
+ <div class="empty">
|
|
|
+ <div class="icon">📦</div>
|
|
|
+ <div class="title">运输计划已归档完成</div>
|
|
|
+ <div>业务详情不可查看</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="footer">
|
|
|
+ <button class="btn btn-ghost" type="button" data-go="list">运输记录</button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- Screen: voided detail -->
|
|
|
+ <div class="screen" data-screen="detail-voided">
|
|
|
+ <div class="nav">运输计划</div>
|
|
|
+ <div class="scroll no-footer-pad">
|
|
|
+ <div class="empty">
|
|
|
+ <div class="icon">⛔</div>
|
|
|
+ <div class="title">运输计划已作废</div>
|
|
|
+ <div>业务详情不可查看</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="footer">
|
|
|
+ <button class="btn btn-ghost" type="button" data-go="list">运输记录</button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- Screen: history list -->
|
|
|
+ <div class="screen" data-screen="list">
|
|
|
+ <div class="nav">
|
|
|
+ <button class="back" type="button" data-go="detail-active">‹ 返回</button>
|
|
|
+ 运输记录
|
|
|
+ </div>
|
|
|
+ <div class="scroll" style="padding-bottom:16px">
|
|
|
+ <div class="filters">
|
|
|
+ <div class="filter-row" style="gap:8px">
|
|
|
+ <button type="button" class="chip on" data-quick="0">今天</button>
|
|
|
+ <button type="button" class="chip" data-quick="1">明天</button>
|
|
|
+ <button type="button" class="chip" data-quick="2">后天</button>
|
|
|
+ </div>
|
|
|
+ <div class="filter-row">
|
|
|
+ <input type="date" id="pickDate" value="2026-08-21" style="height:36px;border:1px solid var(--line);border-radius:8px;padding:0 10px;font-size:13px;width:100%;background:#fff" />
|
|
|
+ </div>
|
|
|
+ <div class="hint" id="filterHint">当前:今天 2026-08-21 · 取货或送货命中</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div id="recordList"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- Static reference: footer always -->
|
|
|
+ <div class="phone-wrap">
|
|
|
+ <div class="phone-label">对照:任意状态底部都有「运输记录」</div>
|
|
|
+ <div class="phone">
|
|
|
+ <div class="nav">运输计划</div>
|
|
|
+ <div class="scroll no-footer-pad">
|
|
|
+ <div class="empty">
|
|
|
+ <div class="icon">📦</div>
|
|
|
+ <div class="title">运输计划已归档完成</div>
|
|
|
+ <div>与现状一致,详情不展示</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="footer">
|
|
|
+ <button class="btn btn-ghost" type="button">运输记录</button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="note">
|
|
|
+ <strong>Demo 说明(已确认部分):</strong><br />
|
|
|
+ 1)「运输记录」按<strong>主车车牌号</strong>聚合历史与后续安排。<br />
|
|
|
+ 2)任意状态底部仅保留「运输记录」;不再提供「返回列表」。<br />
|
|
|
+ 3)筛选:单日日期框 +「今天/明天/后天」快捷;<strong>默认今天</strong>。<br />
|
|
|
+ 4)命中:取货日或送货日<strong>任一等于</strong>所选日。
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <script>
|
|
|
+ const records = [
|
|
|
+ {
|
|
|
+ id: "r1",
|
|
|
+ planNo: "YS20260821001",
|
|
|
+ pickupDate: "2026-08-21",
|
|
|
+ deliveryDate: "2026-08-21",
|
|
|
+ route: "江宁仓库 → 镇江厂区",
|
|
|
+ status: "arranged",
|
|
|
+ statusLabel: "进行中",
|
|
|
+ tag: "ok",
|
|
|
+ screen: "detail-active"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: "r2",
|
|
|
+ planNo: "YS20260821002",
|
|
|
+ pickupDate: "2026-08-21",
|
|
|
+ deliveryDate: "2026-08-22",
|
|
|
+ route: "仪征码头 → 南京港",
|
|
|
+ status: "arranged",
|
|
|
+ statusLabel: "进行中",
|
|
|
+ tag: "ok",
|
|
|
+ screen: "detail-active"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: "r3",
|
|
|
+ planNo: "YS20260818008",
|
|
|
+ pickupDate: "2026-08-18",
|
|
|
+ deliveryDate: "2026-08-18",
|
|
|
+ route: "徐州仓 → 宿迁站",
|
|
|
+ status: "archived",
|
|
|
+ statusLabel: "已归档",
|
|
|
+ tag: "arch",
|
|
|
+ screen: "detail-archived"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: "r4",
|
|
|
+ planNo: "YS20260815003",
|
|
|
+ pickupDate: "2026-08-15",
|
|
|
+ deliveryDate: "2026-08-16",
|
|
|
+ route: "盐城库 → 南通厂",
|
|
|
+ status: "voided",
|
|
|
+ statusLabel: "已作废",
|
|
|
+ tag: "void",
|
|
|
+ screen: "detail-voided"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: "r5",
|
|
|
+ planNo: "YS20260822001",
|
|
|
+ pickupDate: "2026-08-22",
|
|
|
+ deliveryDate: "2026-08-22",
|
|
|
+ route: "连云港 → 淮安仓",
|
|
|
+ status: "arranged",
|
|
|
+ statusLabel: "后续安排",
|
|
|
+ tag: "warn",
|
|
|
+ screen: "detail-active"
|
|
|
+ }
|
|
|
+ ];
|
|
|
+
|
|
|
+ const todayBase = new Date(2026, 7, 21); // demo fixed "today": 2026-08-21
|
|
|
+
|
|
|
+ function fmt(d) {
|
|
|
+ const y = d.getFullYear();
|
|
|
+ const m = String(d.getMonth() + 1).padStart(2, "0");
|
|
|
+ const day = String(d.getDate()).padStart(2, "0");
|
|
|
+ return `${y}-${m}-${day}`;
|
|
|
+ }
|
|
|
+
|
|
|
+ function addDays(base, n) {
|
|
|
+ const d = new Date(base.getTime());
|
|
|
+ d.setDate(d.getDate() + n);
|
|
|
+ return d;
|
|
|
+ }
|
|
|
+
|
|
|
+ const today = fmt(todayBase);
|
|
|
+ const phone = document.getElementById("phone");
|
|
|
+ const listEl = document.getElementById("recordList");
|
|
|
+ const pickDate = document.getElementById("pickDate");
|
|
|
+ const filterHint = document.getElementById("filterHint");
|
|
|
+ const quickBtns = document.querySelectorAll("[data-quick]");
|
|
|
+
|
|
|
+ pickDate.value = today;
|
|
|
+
|
|
|
+ function showScreen(name) {
|
|
|
+ phone.querySelectorAll(".screen").forEach((el) => {
|
|
|
+ el.classList.toggle("active", el.dataset.screen === name);
|
|
|
+ });
|
|
|
+ document.querySelectorAll("#jumpTabs button").forEach((btn) => {
|
|
|
+ const map = {
|
|
|
+ A: "detail-active",
|
|
|
+ B: "detail-archived",
|
|
|
+ C: "list",
|
|
|
+ D: "detail-voided"
|
|
|
+ };
|
|
|
+ btn.classList.toggle("active", map[btn.dataset.jump] === name);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ function matchesDate(r, day) {
|
|
|
+ return r.pickupDate === day || r.deliveryDate === day;
|
|
|
+ }
|
|
|
+
|
|
|
+ function syncQuickActive(day) {
|
|
|
+ quickBtns.forEach((btn) => {
|
|
|
+ const offset = Number(btn.dataset.quick);
|
|
|
+ const target = fmt(addDays(todayBase, offset));
|
|
|
+ btn.classList.toggle("on", target === day);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ function labelFor(day) {
|
|
|
+ if (day === fmt(addDays(todayBase, 0))) return `今天 ${day}`;
|
|
|
+ if (day === fmt(addDays(todayBase, 1))) return `明天 ${day}`;
|
|
|
+ if (day === fmt(addDays(todayBase, 2))) return `后天 ${day}`;
|
|
|
+ return day;
|
|
|
+ }
|
|
|
+
|
|
|
+ function renderList() {
|
|
|
+ const day = (pickDate.value || today).trim();
|
|
|
+ syncQuickActive(day);
|
|
|
+ const filtered = records.filter((r) => matchesDate(r, day));
|
|
|
+ filterHint.textContent = `当前:${labelFor(day)} · 取货或送货命中 · 共 ${filtered.length} 条`;
|
|
|
+
|
|
|
+ if (!filtered.length) {
|
|
|
+ listEl.innerHTML = `<div class="empty"><div class="icon">🗂️</div><div class="title">暂无运输记录</div><div>可点「明天/后天」或另选日期</div></div>`;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ listEl.innerHTML = filtered
|
|
|
+ .map(
|
|
|
+ (r) => `
|
|
|
+ <div class="record" data-screen="${r.screen}" role="button" tabindex="0">
|
|
|
+ <div class="record-top">
|
|
|
+ <div class="record-no">${r.planNo}</div>
|
|
|
+ <span class="tag ${r.tag}">${r.statusLabel}</span>
|
|
|
+ </div>
|
|
|
+ <div class="record-meta">
|
|
|
+ <div>取货:<strong>${r.pickupDate}</strong> · 送货:<strong>${r.deliveryDate}</strong></div>
|
|
|
+ <div>线路:${r.route}</div>
|
|
|
+ </div>
|
|
|
+ </div>`
|
|
|
+ )
|
|
|
+ .join("");
|
|
|
+
|
|
|
+ listEl.querySelectorAll(".record").forEach((el) => {
|
|
|
+ el.addEventListener("click", () => showScreen(el.dataset.screen));
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ phone.addEventListener("click", (e) => {
|
|
|
+ const btn = e.target.closest("[data-go]");
|
|
|
+ if (!btn) return;
|
|
|
+ showScreen(btn.dataset.go);
|
|
|
+ if (btn.dataset.go === "list") renderList();
|
|
|
+ });
|
|
|
+
|
|
|
+ quickBtns.forEach((btn) => {
|
|
|
+ btn.addEventListener("click", () => {
|
|
|
+ pickDate.value = fmt(addDays(todayBase, Number(btn.dataset.quick)));
|
|
|
+ renderList();
|
|
|
+ });
|
|
|
+ });
|
|
|
+ pickDate.addEventListener("change", renderList);
|
|
|
+
|
|
|
+ document.getElementById("jumpTabs").addEventListener("click", (e) => {
|
|
|
+ const btn = e.target.closest("button[data-jump]");
|
|
|
+ if (!btn) return;
|
|
|
+ const map = {
|
|
|
+ A: "detail-active",
|
|
|
+ B: "detail-archived",
|
|
|
+ C: "list",
|
|
|
+ D: "detail-voided"
|
|
|
+ };
|
|
|
+ showScreen(map[btn.dataset.jump]);
|
|
|
+ if (btn.dataset.jump === "C") renderList();
|
|
|
+ });
|
|
|
+
|
|
|
+ renderList();
|
|
|
+ </script>
|
|
|
+</body>
|
|
|
+</html>
|