648 lines
27 KiB
HTML
648 lines
27 KiB
HTML
<!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;
|
||
--bg-page: #f1f5f9;
|
||
--shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||
--shadow-lg: 0 12px 40px rgba(15, 23, 42, 0.14);
|
||
--radius: 10px;
|
||
--warn: #d97706;
|
||
--warn-bg: #fffbeb;
|
||
--warn-border: #fde68a;
|
||
--danger: #dc2626;
|
||
--danger-bg: #fef2f2;
|
||
--danger-border: #fecaca;
|
||
--info: #0284c7;
|
||
--info-bg: #f0f9ff;
|
||
--info-border: #bae6fd;
|
||
--qty-plan: #059669;
|
||
}
|
||
|
||
* { box-sizing: border-box; }
|
||
body {
|
||
margin: 0;
|
||
min-height: 100vh;
|
||
font-family: Inter, -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif;
|
||
font-size: 14px;
|
||
line-height: 1.5;
|
||
color: var(--text);
|
||
background: var(--bg-page);
|
||
}
|
||
|
||
.demo-page { max-width: 1180px; margin: 0 auto; padding: 28px 24px 80px; }
|
||
.demo-head { margin-bottom: 18px; }
|
||
.demo-head h1 { margin: 0 0 8px; font-size: 22px; 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: 900px; }
|
||
.meta { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
|
||
.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 #a7f3d0;
|
||
}
|
||
.pill.muted { background: #f1f5f9; color: var(--text-muted); border-color: #e2e8f0; }
|
||
.pill.warn { background: var(--warn-bg); color: var(--warn); border-color: var(--warn-border); }
|
||
.pill.danger { background: var(--danger-bg); color: var(--danger); border-color: var(--danger-border); }
|
||
|
||
.brief {
|
||
display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 16px;
|
||
}
|
||
@media (max-width: 900px) { .brief { grid-template-columns: 1fr; } }
|
||
.card {
|
||
background: var(--surface); border: 1px solid var(--border);
|
||
border-radius: var(--radius); padding: 14px 16px; box-shadow: var(--shadow);
|
||
}
|
||
.card h2 {
|
||
margin: 0 0 8px; font-size: 14px; font-weight: 600;
|
||
padding-left: 10px; border-left: 3px solid var(--primary);
|
||
color: var(--primary-dark);
|
||
}
|
||
.card.danger-card h2 { border-left-color: var(--danger); color: var(--danger); }
|
||
.card.warn-card h2 { border-left-color: var(--warn); color: var(--warn); }
|
||
.card ul { margin: 0; padding-left: 18px; color: var(--text-muted); font-size: 13px; }
|
||
.card li { margin: 4px 0; }
|
||
.card li strong { color: var(--text); }
|
||
.formula {
|
||
margin-top: 8px; padding: 8px 10px; border-radius: 8px;
|
||
background: var(--primary-bg); color: var(--primary-dark);
|
||
font-size: 12px; font-weight: 500;
|
||
}
|
||
.formula.warn { background: var(--warn-bg); color: #92400e; }
|
||
.formula.danger { background: var(--danger-bg); color: #991b1b; }
|
||
|
||
.scenario-tabs {
|
||
display: flex; gap: 8px; margin-bottom: 14px; flex-wrap: wrap;
|
||
}
|
||
.scenario-tab {
|
||
appearance: none; border: 1px solid var(--border); background: #fff;
|
||
height: 36px; padding: 0 14px; border-radius: 8px; cursor: pointer;
|
||
font-size: 13px; font-weight: 500; color: var(--text);
|
||
}
|
||
.scenario-tab:hover { border-color: #a7f3d0; color: var(--primary-dark); }
|
||
.scenario-tab.active {
|
||
background: var(--primary-bg); border-color: #a7f3d0; color: var(--primary-dark);
|
||
}
|
||
|
||
.panel {
|
||
background: var(--surface); border: 1px solid var(--border);
|
||
border-radius: 12px; box-shadow: var(--shadow-lg); overflow: hidden;
|
||
}
|
||
.panel-top {
|
||
display: flex; align-items: center; justify-content: space-between;
|
||
gap: 12px; padding: 14px 18px; border-bottom: 1px solid var(--border); flex-wrap: wrap;
|
||
}
|
||
.panel-top h3 {
|
||
margin: 0; font-size: 16px; font-weight: 600;
|
||
display: inline-flex; align-items: center; gap: 8px;
|
||
}
|
||
.panel-top h3::before {
|
||
content: ""; width: 3px; height: 16px; border-radius: 2px; background: var(--primary);
|
||
}
|
||
.toolbar { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
|
||
|
||
.btn {
|
||
appearance: none; display: inline-flex; align-items: center; gap: 6px;
|
||
height: 32px; padding: 0 12px; border-radius: 8px; font-size: 13px; font-weight: 500;
|
||
border: 1px solid var(--border); background: #fff; color: var(--text); cursor: pointer;
|
||
}
|
||
.btn:hover { border-color: #a7f3d0; color: var(--primary-dark); }
|
||
.btn.primary { background: var(--primary); border-color: var(--primary); color: #fff; }
|
||
.btn.primary:hover { background: var(--primary-dark); border-color: var(--primary-dark); color: #fff; }
|
||
.btn.ghost { background: transparent; }
|
||
.btn.warn { background: var(--warn); border-color: var(--warn); color: #fff; }
|
||
.btn.warn:hover { filter: brightness(0.95); color: #fff; }
|
||
.btn.danger { background: var(--danger); border-color: var(--danger); color: #fff; }
|
||
.btn.danger:hover { filter: brightness(0.95); color: #fff; }
|
||
|
||
.kv-row {
|
||
display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px;
|
||
padding: 14px 18px; border-bottom: 1px solid #eef2f7;
|
||
}
|
||
@media (max-width: 900px) { .kv-row { grid-template-columns: 1fr 1fr; } }
|
||
.kv-item .label { font-size: 11px; color: var(--text-muted); margin-bottom: 2px; }
|
||
.kv-item .value { font-size: 13px; font-weight: 500; }
|
||
|
||
.section {
|
||
padding: 14px 18px 18px;
|
||
}
|
||
.section-title {
|
||
margin: 0 0 10px; font-size: 13px; font-weight: 600; color: var(--primary-dark);
|
||
}
|
||
|
||
table {
|
||
width: 100%; border-collapse: collapse; font-size: 13px;
|
||
}
|
||
th, td {
|
||
border: 1px solid var(--border); padding: 8px 10px; text-align: left;
|
||
vertical-align: middle;
|
||
}
|
||
th {
|
||
background: #f8fafc; font-weight: 600; color: #334155; font-size: 12px;
|
||
}
|
||
th.num, td.num { text-align: right; font-variant-numeric: tabular-nums; }
|
||
th.plan-qty, td.plan-qty { color: var(--qty-plan); }
|
||
th.plan-qty { background: #ecfdf5; }
|
||
td.over { color: var(--danger); font-weight: 600; background: #fef2f2; }
|
||
.tag {
|
||
display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 4px;
|
||
font-size: 12px; font-weight: 500; color: #fff; background: var(--primary-dark);
|
||
}
|
||
.tag.warn { background: var(--warn); }
|
||
.tag.info { background: var(--info); }
|
||
.tag.muted { background: transparent; color: var(--text); border: 1px solid #cbd5e1; }
|
||
|
||
.hint-inline {
|
||
margin-top: 10px; padding: 10px 12px; border-radius: 8px;
|
||
font-size: 13px; display: none;
|
||
}
|
||
.hint-inline.show { display: block; }
|
||
.hint-inline.danger {
|
||
background: var(--danger-bg); border: 1px solid var(--danger-border); color: #991b1b;
|
||
}
|
||
.hint-inline.warn {
|
||
background: var(--warn-bg); border: 1px solid var(--warn-border); color: #92400e;
|
||
}
|
||
.hint-inline.info {
|
||
background: var(--info-bg); border: 1px solid var(--info-border); color: #075985;
|
||
}
|
||
.hint-inline strong { font-weight: 600; }
|
||
|
||
/* Modal */
|
||
.mask {
|
||
position: fixed; inset: 0; background: rgba(15, 23, 42, 0.45);
|
||
display: none; align-items: center; justify-content: center;
|
||
padding: 24px; z-index: 50;
|
||
/* 无背景模糊,对齐规范 */
|
||
backdrop-filter: none;
|
||
}
|
||
.mask.show { display: flex; }
|
||
.modal {
|
||
width: min(780px, 100%);
|
||
background: #fff; border-radius: 12px;
|
||
border: 1px solid var(--border); box-shadow: var(--shadow-lg);
|
||
overflow: hidden;
|
||
}
|
||
.modal-header {
|
||
display: flex; align-items: center; justify-content: space-between;
|
||
padding: 14px 18px; border-bottom: 1px solid var(--border);
|
||
}
|
||
.modal-header h4 { margin: 0; font-size: 15px; font-weight: 600; }
|
||
.modal-body { padding: 16px 18px; }
|
||
.modal-body p { margin: 0 0 10px; color: var(--text); font-size: 13px; }
|
||
.modal-body .calc {
|
||
margin: 12px 0; padding: 10px 12px; border-radius: 8px;
|
||
background: #f8fafc; border: 1px solid #e2e8f0; font-size: 13px;
|
||
}
|
||
.modal-body .calc .row {
|
||
display: flex; justify-content: space-between; gap: 12px; padding: 3px 0;
|
||
}
|
||
.modal-body .calc .row.total {
|
||
margin-top: 6px; padding-top: 8px; border-top: 1px dashed #cbd5e1;
|
||
font-weight: 600;
|
||
}
|
||
.modal-body .calc .row.over .v { color: var(--danger); }
|
||
.modal-footer {
|
||
display: flex; justify-content: flex-end; gap: 8px;
|
||
padding: 12px 18px; border-top: 1px solid var(--border);
|
||
}
|
||
|
||
.choice-note {
|
||
margin-top: 16px; padding: 12px 14px; border-radius: 10px;
|
||
background: #fff; border: 1px dashed #a7f3d0; color: var(--text-muted); font-size: 13px;
|
||
}
|
||
.choice-note strong { color: var(--primary-dark); }
|
||
|
||
.hidden { display: none !important; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="demo-page">
|
||
<header class="demo-head">
|
||
<h1>运输计划安排 · <span>合同数量校验</span> & 框架合同提醒</h1>
|
||
<p>
|
||
预览「安排运输」时的两类提示:① 有数量合同 — 已安排 + 本次是否超合同总量;
|
||
② 框架采购/销售合同(无固定数量)— 每次提醒累计已安排数量。数量口径对齐合同详情三列:
|
||
<code>已安排合计 = 已归档 + 未归档已安排</code>(按停靠段 <code>plan_qty</code> / product_id)。
|
||
</p>
|
||
<div class="meta">
|
||
<span class="pill">路径 · /#/pl/plan-module/plan</span>
|
||
<span class="pill muted">触发点 · 安排运输 / 保存并安排</span>
|
||
<span class="pill danger">场景 A · 超量硬拦截</span>
|
||
<span class="pill warn">场景 B · 框架累计提醒</span>
|
||
<span class="pill">场景 C · 未超限提醒剩余</span>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="brief">
|
||
<div class="card danger-card">
|
||
<h2>A. 有数量合同(销售/采购等)</h2>
|
||
<ul>
|
||
<li>合同产品行存在<strong>有效数量</strong>时参与校验</li>
|
||
<li>校验式:<strong>已安排合计 + 本次 planQty ≤ 合同数量</strong></li>
|
||
<li>超限:安排<strong>前提交拦截</strong>,弹窗说明差额,必须改数量</li>
|
||
<li>未超限:安排<strong>成功之后</strong>弹窗提醒<strong>剩余可安排量</strong></li>
|
||
<li>汇总口径:有绑合同的段都校验;已安排合计按该合同挂接停靠段(同合同详情三列)</li>
|
||
</ul>
|
||
<div class="formula danger">超限 → 事前硬拦;未超限 → 成功后提醒剩余</div>
|
||
</div>
|
||
<div class="card warn-card">
|
||
<h2>B. 框架合同(无数量)</h2>
|
||
<ul>
|
||
<li>类型:<strong>框架销售 / 框架采购</strong>(含历史 framework)</li>
|
||
<li>产品数量为「按客户需求」或空 → <strong>不拦数量</strong></li>
|
||
<li>安排<strong>成功之后</strong>提醒:本次 + 累计已安排(无「剩余」)</li>
|
||
</ul>
|
||
<div class="formula warn">成功后提醒,不阻断安排</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="scenario-tabs" role="tablist">
|
||
<button type="button" class="scenario-tab active" data-scenario="fixed" role="tab">场景 A · 有数量合同超量</button>
|
||
<button type="button" class="scenario-tab" data-scenario="framework" role="tab">场景 B · 框架合同提醒</button>
|
||
<button type="button" class="scenario-tab" data-scenario="ok" role="tab">场景 C · 未超限 · 提醒剩余量</button>
|
||
</div>
|
||
|
||
<!-- 场景 A -->
|
||
<section id="panel-fixed" class="panel" data-panel="fixed">
|
||
<div class="panel-top">
|
||
<h3>安排运输 · 绑定有数量合同</h3>
|
||
<div class="toolbar">
|
||
<span class="tag">销售合同</span>
|
||
<button type="button" class="btn primary" id="btn-arrange-fixed">▶ 安排运输</button>
|
||
</div>
|
||
</div>
|
||
<div class="kv-row">
|
||
<div class="kv-item"><div class="label">计划编号</div><div class="value">YP20260830012</div></div>
|
||
<div class="kv-item"><div class="label">装货合同</div><div class="value">HT-2026-0318 · 硫酸销售合同</div></div>
|
||
<div class="kv-item"><div class="label">合同数量口径</div><div class="value">产品行 quantity</div></div>
|
||
<div class="kv-item"><div class="label">策略</div><div class="value">超量硬拦截</div></div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="section-title">本次装货产品 vs 合同用量</div>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>产品</th>
|
||
<th class="num">合同数量</th>
|
||
<th class="num plan-qty">已安排合计</th>
|
||
<th class="num">本次安排</th>
|
||
<th class="num">安排后合计</th>
|
||
<th class="num">剩余可安排</th>
|
||
<th>结果</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>98% 硫酸</td>
|
||
<td class="num">100.000</td>
|
||
<td class="num plan-qty">80.000</td>
|
||
<td class="num">30.000</td>
|
||
<td class="num over">110.000</td>
|
||
<td class="num over">-10.000</td>
|
||
<td><span class="tag" style="background:#dc2626">超量</span></td>
|
||
</tr>
|
||
<tr>
|
||
<td>液碱 32%</td>
|
||
<td class="num">50.000</td>
|
||
<td class="num plan-qty">20.000</td>
|
||
<td class="num">10.000</td>
|
||
<td class="num">30.000</td>
|
||
<td class="num">20.000</td>
|
||
<td><span class="tag">正常</span></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<div class="hint-inline danger show" id="inline-fixed">
|
||
<strong>校验提示:</strong>产品「98% 硫酸」安排后合计 110 超过合同数量 100(超出 10)。请调减本次数量或更换合同后再安排。
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 场景 B -->
|
||
<section id="panel-framework" class="panel hidden" data-panel="framework">
|
||
<div class="panel-top">
|
||
<h3>安排运输 · 框架销售合同</h3>
|
||
<div class="toolbar">
|
||
<span class="tag warn">框架销售合同</span>
|
||
<button type="button" class="btn primary" id="btn-arrange-fw">▶ 安排运输</button>
|
||
</div>
|
||
</div>
|
||
<div class="kv-row">
|
||
<div class="kv-item"><div class="label">计划编号</div><div class="value">YP20260830018</div></div>
|
||
<div class="kv-item"><div class="label">送货合同</div><div class="value">HT-KJ-2026-008 · 年度框架销售</div></div>
|
||
<div class="kv-item"><div class="label">合同数量</div><div class="value">按客户需求(无固定量)</div></div>
|
||
<div class="kv-item"><div class="label">校验策略</div><div class="value">仅累计提醒,不拦截</div></div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="section-title">本次产品安排(框架无总量上限)</div>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>产品</th>
|
||
<th class="num">合同数量</th>
|
||
<th class="num plan-qty">已安排合计</th>
|
||
<th class="num">本次安排</th>
|
||
<th class="num plan-qty">安排后已安排</th>
|
||
<th>结果</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>工业盐酸</td>
|
||
<td class="num" style="color:var(--text-muted)">按客户需求</td>
|
||
<td class="num plan-qty">126.500</td>
|
||
<td class="num">28.000</td>
|
||
<td class="num plan-qty">154.500</td>
|
||
<td><span class="tag warn">提醒</span></td>
|
||
</tr>
|
||
<tr>
|
||
<td>片碱</td>
|
||
<td class="num" style="color:var(--text-muted)">按客户需求</td>
|
||
<td class="num plan-qty">40.000</td>
|
||
<td class="num">12.000</td>
|
||
<td class="num plan-qty">52.000</td>
|
||
<td><span class="tag warn">提醒</span></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<div class="hint-inline warn show">
|
||
<strong>框架合同提醒(安排成功后):</strong>无固定数量上限。工业盐酸累计已安排 <strong>154.500</strong>,片碱累计已安排 <strong>52.000</strong>。
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 场景 C:未超限,提醒剩余 -->
|
||
<section id="panel-ok" class="panel hidden" data-panel="ok">
|
||
<div class="panel-top">
|
||
<h3>安排运输 · 有数量且未超限</h3>
|
||
<div class="toolbar">
|
||
<span class="tag">采购合同</span>
|
||
<button type="button" class="btn primary" id="btn-arrange-ok">▶ 安排运输</button>
|
||
</div>
|
||
</div>
|
||
<div class="kv-row">
|
||
<div class="kv-item"><div class="label">计划编号</div><div class="value">YP20260830021</div></div>
|
||
<div class="kv-item"><div class="label">装货合同</div><div class="value">HT-CG-2026-102 · 液碱采购</div></div>
|
||
<div class="kv-item"><div class="label">合同数量</div><div class="value">200.000</div></div>
|
||
<div class="kv-item"><div class="label">校验结果</div><div class="value">通过 · 成功后提醒剩余</div></div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="section-title">本次产品安排</div>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>产品</th>
|
||
<th class="num">合同数量</th>
|
||
<th class="num plan-qty">已安排合计</th>
|
||
<th class="num">本次安排</th>
|
||
<th class="num">安排后合计</th>
|
||
<th class="num">安排后剩余</th>
|
||
<th>结果</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>液碱 32%</td>
|
||
<td class="num">200.000</td>
|
||
<td class="num plan-qty">150.000</td>
|
||
<td class="num">40.000</td>
|
||
<td class="num">190.000</td>
|
||
<td class="num plan-qty">10.000</td>
|
||
<td><span class="tag">成功后提醒</span></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<div class="hint-inline info show">
|
||
<strong>未超限:</strong>先完成安排;成功后再弹窗告知「剩余可安排量」(知悉即可,非二次确认)。
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<p class="choice-note">
|
||
<strong>已确认:</strong>超量事前硬拦;未超限 / 框架 → 安排成功后弹窗提醒;校验范围 = 有绑合同的段,已安排合计口径对齐合同详情三列。点击「安排运输」预览弹窗。
|
||
</p>
|
||
</div>
|
||
|
||
<!-- 超量弹窗:硬拦 · 按合同分组表格 -->
|
||
<div class="mask" id="mask-over-hard" role="dialog" aria-modal="true">
|
||
<div class="modal">
|
||
<div class="modal-header">
|
||
<h4 style="color:var(--danger)">无法安排运输</h4>
|
||
<button type="button" class="btn ghost" data-close>×</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<p style="margin:0 0 12px;color:var(--text-muted);font-size:13px;">以下产品「已安排 + 本次」超过合同数量,请调整后再安排:</p>
|
||
<div style="margin:0 0 14px;">
|
||
<div style="font-size:14px;font-weight:600;margin:0 0 8px;padding-left:8px;border-left:3px solid var(--primary);">安徽某某化工 - HT-2026-0318(装货)</div>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>产品名称</th>
|
||
<th>规格型号</th>
|
||
<th class="num">合同数量</th>
|
||
<th>单位</th>
|
||
<th class="num">已安排</th>
|
||
<th class="num">剩余</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>98% 硫酸</td>
|
||
<td>工业级</td>
|
||
<td class="num">100.000</td>
|
||
<td>吨</td>
|
||
<td class="num">110.000</td>
|
||
<td class="num over">-10.000</td>
|
||
</tr>
|
||
<tr>
|
||
<td>液碱 32%</td>
|
||
<td>—</td>
|
||
<td class="num">50.000</td>
|
||
<td>吨</td>
|
||
<td class="num">30.000</td>
|
||
<td class="num plan-qty">20.000</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn primary" data-close>✓ 知道了</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 框架提醒 · 按合同分组表格 -->
|
||
<div class="mask" id="mask-framework" role="dialog" aria-modal="true">
|
||
<div class="modal">
|
||
<div class="modal-header">
|
||
<h4 style="color:var(--warn)">安排成功 · 框架合同累计</h4>
|
||
<button type="button" class="btn ghost" data-close>×</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<p style="margin:0 0 12px;color:var(--text-muted);font-size:13px;">运输安排已成功。框架合同无固定数量上限,累计已安排如下:</p>
|
||
<div style="margin:0 0 14px;">
|
||
<div style="font-size:14px;font-weight:600;margin:0 0 8px;padding-left:8px;border-left:3px solid var(--primary);">某某贸易公司 - HT-KJ-2026-008(送货)</div>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>产品名称</th>
|
||
<th>规格型号</th>
|
||
<th class="num">合同数量</th>
|
||
<th>单位</th>
|
||
<th class="num">已安排</th>
|
||
<th class="num">剩余</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>工业盐酸</td>
|
||
<td>31%</td>
|
||
<td class="num" style="color:var(--text-muted)">按客户需求</td>
|
||
<td>吨</td>
|
||
<td class="num plan-qty">154.500</td>
|
||
<td class="num">—</td>
|
||
</tr>
|
||
<tr>
|
||
<td>片碱</td>
|
||
<td>—</td>
|
||
<td class="num" style="color:var(--text-muted)">按客户需求</td>
|
||
<td>吨</td>
|
||
<td class="num plan-qty">52.000</td>
|
||
<td class="num">—</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn primary" data-close>✓ 知道了</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 未超限:双侧合同示意 -->
|
||
<div class="mask" id="mask-ok" role="dialog" aria-modal="true">
|
||
<div class="modal">
|
||
<div class="modal-header">
|
||
<h4 style="color:var(--primary-dark)">安排成功 · 合同剩余数量</h4>
|
||
<button type="button" class="btn ghost" data-close>×</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<p style="margin:0 0 12px;color:var(--text-muted);font-size:13px;">运输安排已成功。各产品剩余可安排量如下:</p>
|
||
<div style="margin:0 0 14px;">
|
||
<div style="font-size:14px;font-weight:600;margin:0 0 8px;padding-left:8px;border-left:3px solid var(--primary);">云栋供应商 - HT-CG-2026-102(装货)</div>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>产品名称</th>
|
||
<th>规格型号</th>
|
||
<th class="num">合同数量</th>
|
||
<th>单位</th>
|
||
<th class="num">已安排</th>
|
||
<th class="num">剩余</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>液碱 32%</td>
|
||
<td>—</td>
|
||
<td class="num">200.000</td>
|
||
<td>吨</td>
|
||
<td class="num">190.000</td>
|
||
<td class="num plan-qty">10.000</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div style="margin:0 0 4px;">
|
||
<div style="font-size:14px;font-weight:600;margin:0 0 8px;padding-left:8px;border-left:3px solid var(--primary);">某某贸易公司 - HT-XS-2026-088(送货)</div>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>产品名称</th>
|
||
<th>规格型号</th>
|
||
<th class="num">合同数量</th>
|
||
<th>单位</th>
|
||
<th class="num">已安排</th>
|
||
<th class="num">剩余</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>液碱 32%</td>
|
||
<td>—</td>
|
||
<td class="num">180.000</td>
|
||
<td>吨</td>
|
||
<td class="num">40.000</td>
|
||
<td class="num plan-qty">140.000</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn primary" data-close>✓ 知道了</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
(function () {
|
||
function showPanel(name) {
|
||
document.querySelectorAll('[data-panel]').forEach(function (el) {
|
||
el.classList.toggle('hidden', el.getAttribute('data-panel') !== name)
|
||
})
|
||
document.querySelectorAll('.scenario-tab').forEach(function (tab) {
|
||
tab.classList.toggle('active', tab.getAttribute('data-scenario') === name)
|
||
})
|
||
}
|
||
document.querySelectorAll('.scenario-tab').forEach(function (tab) {
|
||
tab.addEventListener('click', function () {
|
||
showPanel(tab.getAttribute('data-scenario'))
|
||
})
|
||
})
|
||
|
||
function openMask(id) {
|
||
document.getElementById(id).classList.add('show')
|
||
}
|
||
function closeAll() {
|
||
document.querySelectorAll('.mask').forEach(function (m) { m.classList.remove('show') })
|
||
}
|
||
document.querySelectorAll('[data-close]').forEach(function (btn) {
|
||
btn.addEventListener('click', closeAll)
|
||
})
|
||
document.querySelectorAll('.mask').forEach(function (mask) {
|
||
mask.addEventListener('click', function (e) {
|
||
if (e.target === mask) closeAll()
|
||
})
|
||
})
|
||
|
||
document.getElementById('btn-arrange-fixed').addEventListener('click', function () {
|
||
openMask('mask-over-hard')
|
||
})
|
||
document.getElementById('btn-arrange-fw').addEventListener('click', function () {
|
||
openMask('mask-framework')
|
||
})
|
||
document.getElementById('btn-arrange-ok').addEventListener('click', function () {
|
||
openMask('mask-ok')
|
||
})
|
||
})()
|
||
</script>
|
||
</body>
|
||
</html>
|