Files
shanxia2.0/docs/fresh-mint-crm-contract-detail-plan-tab-demo.html
T
2026-08-30 18:33:13 +08:00

681 lines
29 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>Fresh Mint · 合同详情 · 运输计划 Tab &amp; 产品安排数量 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: #f1f5f9;
--row-alt: #fafafa;
--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;
--danger: #dc2626;
/* 新增安排数量列:绿色字,便于与原有金额列区分 */
--qty-plan: #059669;
--load-accent: #059669;
--load-bg: #ecfdf5;
--delivery-accent: #0284c7;
--delivery-bg: #f0f9ff;
--plan-divider: #cbd5e1;
--plan-cell-bg: #f8fffc;
}
* { 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: 1320px; margin: 0 auto; padding: 28px 24px 80px; }
.demo-head { margin-bottom: 20px; }
.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: 920px; }
.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; }
.brief {
display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 18px;
}
@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 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;
}
/* 弹窗外壳 */
.dialog-shell {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px;
box-shadow: var(--shadow-lg);
overflow: hidden;
}
.dialog-header {
display: flex; align-items: center; justify-content: space-between;
padding: 14px 20px; border-bottom: 1px solid var(--border);
}
.dialog-header h3 { margin: 0; font-size: 16px; font-weight: 600; }
.dialog-close {
width: 28px; height: 28px; border: none; background: transparent;
color: var(--text-muted); font-size: 18px; cursor: default; border-radius: 6px;
}
.detail-header {
display: flex; align-items: flex-start; justify-content: space-between;
gap: 16px; padding: 16px 20px 8px; flex-wrap: wrap;
}
.detail-title {
font-size: 15px; font-weight: 600; display: inline-flex; align-items: center; gap: 10px;
}
.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);
}
.detail-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.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: #fff; }
/* Tabs */
.tabs {
display: flex; gap: 0; padding: 0 20px;
border-bottom: 1px solid var(--border); overflow-x: auto;
}
.tab {
appearance: none; border: none; background: transparent;
padding: 12px 16px; font-size: 14px; font-weight: 500;
color: var(--text-muted); cursor: pointer; position: relative; white-space: nowrap;
}
.tab:hover { color: var(--primary-dark); }
.tab.active { color: var(--primary-dark); }
.tab.active::after {
content: ""; position: absolute; left: 12px; right: 12px; bottom: 0;
height: 2px; background: var(--primary); border-radius: 2px 2px 0 0;
}
.tab .new-badge {
margin-left: 6px; font-size: 11px; padding: 1px 6px; border-radius: 999px;
background: var(--primary-bg); color: var(--primary-dark); border: 1px solid #a7f3d0;
font-weight: 600;
}
.tab-panels { padding: 16px 20px 24px; }
.tab-panel { display: none; }
.tab-panel.active { display: block; }
.section-title {
margin: 0 0 12px; font-size: 13px; font-weight: 600; color: var(--text-muted);
display: flex; align-items: center; gap: 8px;
}
.section-title::before {
content: ""; width: 3px; height: 14px; background: var(--primary); border-radius: 2px;
}
.kv-grid {
display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px 16px;
margin-bottom: 20px;
}
@media (max-width: 1100px) { .kv-grid { grid-template-columns: repeat(2, 1fr); } }
.kv-item {
background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 8px 10px;
}
.kv-item .label { font-size: 11px; color: var(--text-muted); margin-bottom: 2px; }
.kv-item .value { font-size: 13px; font-weight: 500; color: var(--text); }
.divider-label {
display: flex; align-items: center; gap: 12px; margin: 8px 0 12px;
color: var(--text-muted); font-size: 13px; font-weight: 500;
}
.divider-label::before, .divider-label::after {
content: ""; flex: 1; height: 1px; background: var(--border);
}
.table-wrap {
border: 1px solid var(--border); border-radius: 8px; overflow: auto;
max-width: 100%;
}
table.list-table {
width: 100%; border-collapse: collapse; min-width: 1280px;
font-size: 13px;
}
table.list-table thead th {
background: var(--table-head); color: var(--text-muted);
font-weight: 600; text-align: left; padding: 10px 12px;
border-bottom: 1px solid var(--border); white-space: nowrap;
}
table.list-table tbody td {
padding: 10px 12px; border-bottom: 1px solid #eef2f7;
color: var(--text); white-space: nowrap;
}
table.list-table tbody tr:nth-child(even) td { background: var(--row-alt); }
table.list-table tbody tr:last-child td { border-bottom: none; }
.num { text-align: right; font-variant-numeric: tabular-nums; }
.center { text-align: center; }
.money { font-variant-numeric: tabular-nums; }
/* 新增三列:绿色字 + 浅绿表头提示 */
th.col-plan-qty, td.col-plan-qty {
color: var(--qty-plan) !important;
font-weight: 600;
}
th.col-plan-qty {
background: #ecfdf5 !important;
border-bottom-color: #a7f3d0 !important;
}
th.col-plan-qty .th-sub {
display: block; font-size: 11px; font-weight: 500; opacity: 0.85; margin-top: 2px;
}
.hint-bar {
margin-top: 10px; padding: 8px 12px; border-radius: 8px;
background: var(--primary-bg); border: 1px dashed #a7f3d0;
color: var(--primary-dark); font-size: 12px;
}
/* 运输计划 Tab —— 对齐 pl/plan 列表合并单元格样式 */
.plan-toolbar {
display: flex; align-items: center; gap: 12px; margin-bottom: 12px; flex-wrap: wrap;
}
.plan-toolbar .count { color: var(--text-muted); font-size: 13px; }
.pl-merge-wrap {
border: 1px solid var(--border); border-radius: 8px; overflow: auto;
}
table.pl-merge-table {
width: 100%; border-collapse: collapse; min-width: 1280px;
font-size: 13px;
}
table.pl-merge-table thead th {
background: var(--table-head); color: var(--text-muted);
font-weight: 600; text-align: center; padding: 10px 10px;
border-bottom: 1px solid var(--border); white-space: nowrap;
}
table.pl-merge-table thead th.th-left { text-align: left; }
table.pl-merge-table tbody td {
padding: 10px 10px; border-bottom: 1px solid #eef2f7;
vertical-align: middle; text-align: center; white-space: nowrap;
}
table.pl-merge-table tbody td.td-left { text-align: left; white-space: normal; }
table.pl-merge-table tbody td.td-plan {
background: var(--plan-cell-bg);
border-right: 1px solid #e2e8f0;
}
table.pl-merge-table tbody tr.row-load td.td-stop { background: var(--load-bg); }
table.pl-merge-table tbody tr.row-delivery td.td-stop { background: #fafcff; }
table.pl-merge-table tbody tr.plan-end td {
border-bottom: 2px solid var(--plan-divider);
}
.pl-link {
appearance: none; border: none; background: transparent;
color: var(--primary-dark); font-weight: 700; font-size: 14px;
cursor: pointer; padding: 0; text-decoration: none;
}
.pl-link:hover { text-decoration: underline; }
.pl-tag {
display: inline-flex; padding: 2px 8px; border-radius: 4px;
font-size: 12px; font-weight: 600; color: #fff; white-space: nowrap;
}
.pl-tag.success { background: var(--primary-dark); }
.pl-tag.warning { background: var(--warn); }
.pl-tag.danger { background: var(--danger); }
.pl-muted { color: var(--text-muted); font-size: 12px; }
.stop-tag {
display: inline-flex; align-items: center;
padding: 2px 9px; border-radius: 999px;
font-size: 11px; font-weight: 700;
}
.stop-tag.load {
background: var(--load-bg); color: var(--load-accent);
border: 1px solid #a7f3d0;
}
.stop-tag.delivery {
background: var(--delivery-bg); color: var(--delivery-accent);
border: 1px solid #bae6fd;
}
.customer { font-weight: 600; }
.internal {
display: inline-block; margin-left: 4px;
font-size: 10px; font-weight: 600; color: var(--primary-dark);
background: var(--primary-bg); border: 1px solid #a7f3d0;
border-radius: 4px; padding: 0 4px; vertical-align: middle;
}
.addr-block { text-align: left; }
.addr-block .addr { font-size: 12px; color: var(--text); }
.addr-block .time { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
.product-stack { text-align: left; }
.product-stack > div + div { margin-top: 3px; }
.qty { color: var(--primary-dark); font-weight: 700; }
.empty {
padding: 40px; text-align: center; color: var(--text-muted); font-size: 13px;
}
.legend {
margin-top: 18px; display: flex; flex-wrap: wrap; gap: 16px;
font-size: 12px; color: var(--text-muted);
}
.legend span { display: inline-flex; align-items: center; gap: 6px; }
.swatch {
width: 12px; height: 12px; border-radius: 3px; background: var(--qty-plan);
}
</style>
</head>
<body>
<div class="demo-page">
<header class="demo-head">
<h1>合同详情 · <span>运输计划</span> Tab &amp; 产品安排数量</h1>
<p>
预览 CRM【合同详情】弹窗:①「合同信息」产品明细在「税费(元)」后新增三列(绿色字);
② 新增「运输计划」Tab,列表可查看计划详情。点击下方 Tab 切换查看。
</p>
<div class="meta">
<span class="pill">Fresh Mint</span>
<span class="pill muted">ContractDetailDialog</span>
<span class="pill muted">绿色列 = 运输安排汇总</span>
</div>
</header>
<div class="brief">
<div class="card">
<h2>产品明细新增列(绿色字)</h2>
<ul>
<li><strong>已归档数量</strong>:关联本产品、且计划已归档的安排数量合计</li>
<li><strong>未归档已安排</strong>:关联本产品、未归档但已安排的数量合计</li>
<li><strong>已安排合计</strong>:前两列之和</li>
</ul>
<div class="formula">已安排合计 = 已归档数量 + 未归档已安排</div>
</div>
<div class="card">
<h2>运输计划 Tab</h2>
<ul>
<li>列表样式对齐线上<strong>运输计划</strong>页:计划主信息合并单元格 + 装/送货段分行</li>
<li>点击<strong>计划编号</strong>打开只读详情(与列表一致,无单独操作列)</li>
<li>本 Demo 默认打开「运输计划」Tab 便于预览</li>
</ul>
</div>
</div>
<div class="dialog-shell" role="dialog" aria-label="合同详情">
<div class="dialog-header">
<h3>合同详情</h3>
<button class="dialog-close" type="button" aria-label="关闭">×</button>
</div>
<div class="detail-header">
<div class="detail-title">
HT-2026-0318 - 硫酸销售合同(安徽某某化工)
<span class="tag">执行中</span>
</div>
<div class="detail-actions">
<button class="btn ghost" type="button">合同复制</button>
<button class="btn ghost" type="button">打印</button>
<button class="btn ghost" type="button">完成合同</button>
</div>
</div>
<div class="tabs" role="tablist">
<button class="tab" type="button" data-tab="contract" role="tab">合同信息</button>
<button class="tab active" type="button" data-tab="plans" role="tab">
运输计划<span class="new-badge">新</span>
</button>
<button class="tab" type="button" data-tab="payment" role="tab">回款记录</button>
<button class="tab" type="button" data-tab="invoice" role="tab">开票记录</button>
<button class="tab" type="button" data-tab="approval" role="tab">审批流程</button>
<button class="tab" type="button" data-tab="log" role="tab">操作日志</button>
</div>
<div class="tab-panels">
<!-- 合同信息 -->
<div class="tab-panel" id="panel-contract" role="tabpanel">
<div class="section-title">基本信息(示意)</div>
<div class="kv-grid">
<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">硫酸销售合同</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">¥1,286,400.00</div></div>
</div>
<div class="divider-label">产品明细</div>
<div class="table-wrap">
<table class="list-table">
<thead>
<tr>
<th class="center">序号</th>
<th>产品名称</th>
<th>型号/规格</th>
<th class="center">单位</th>
<th class="num">数量</th>
<th class="num">含税单价(元)</th>
<th class="num">含税总价(元)</th>
<th class="num">税费(元)</th>
<th class="num col-plan-qty">
已归档数量
<span class="th-sub">计划已归档</span>
</th>
<th class="num col-plan-qty">
未归档已安排
<span class="th-sub">已安排未归档</span>
</th>
<th class="num col-plan-qty">
已安排合计
<span class="th-sub">归档 + 未归档</span>
</th>
<th>包装规格</th>
<th>送货方式</th>
</tr>
</thead>
<tbody>
<tr>
<td class="center">1</td>
<td>工业硫酸</td>
<td>98%</td>
<td class="center">吨</td>
<td class="num">500.000</td>
<td class="num money">¥1,280.00</td>
<td class="num money">¥640,000.00</td>
<td class="num money">¥73,982.30</td>
<td class="num col-plan-qty">120.000</td>
<td class="num col-plan-qty">80.000</td>
<td class="num col-plan-qty">200.000</td>
<td>槽罐</td>
<td>送货上门</td>
</tr>
<tr>
<td class="center">2</td>
<td>盐酸</td>
<td>31%</td>
<td class="center">吨</td>
<td class="num">300.000</td>
<td class="num money">¥680.00</td>
<td class="num money">¥204,000.00</td>
<td class="num money">¥23,575.22</td>
<td class="num col-plan-qty">50.000</td>
<td class="num col-plan-qty">0.000</td>
<td class="num col-plan-qty">50.000</td>
<td>吨桶</td>
<td>客户自提</td>
</tr>
<tr>
<td class="center">3</td>
<td>液碱</td>
<td>32%</td>
<td class="center">吨</td>
<td class="num">400.000</td>
<td class="num money">¥1,106.00</td>
<td class="num money">¥442,400.00</td>
<td class="num money">¥51,132.74</td>
<td class="num col-plan-qty">0.000</td>
<td class="num col-plan-qty">100.000</td>
<td class="num col-plan-qty">100.000</td>
<td>槽罐</td>
<td>送货上门</td>
</tr>
</tbody>
</table>
</div>
<div class="hint-bar">
绿色三列示意:与左侧金额列视觉区分。示例:工业硫酸 120 + 80 = 200;盐酸 50 + 0 = 50;液碱 0 + 100 = 100。
</div>
</div>
<!-- 运输计划:对齐 pl/plan 列表合并单元格 -->
<div class="tab-panel active" id="panel-plans" role="tabpanel">
<div class="plan-toolbar">
<span class="count">共关联 <strong style="color:var(--text)">2</strong> 条运输计划(按计划计数,非按段)</span>
</div>
<div class="pl-merge-wrap">
<table class="pl-merge-table">
<thead>
<tr>
<th style="width:52px">序号</th>
<th style="width:160px">计划编号</th>
<th style="width:88px">跟进状态</th>
<th style="width:100px">计划日期</th>
<th style="width:80px">单据类型</th>
<th style="width:110px">车牌号</th>
<th style="width:88px">跟进人</th>
<th style="width:76px">段次</th>
<th class="th-left" style="width:180px">客户</th>
<th class="th-left" style="width:180px">地址 / 时间</th>
<th class="th-left" style="width:140px">产品名称</th>
<th style="width:88px">计划数量</th>
<th style="width:72px">地磅</th>
</tr>
</thead>
<tbody>
<!-- 计划 1:1装 + 1送 → rowspan=2 -->
<tr class="row-load">
<td class="td-plan" rowspan="2">1</td>
<td class="td-plan" rowspan="2">
<button class="pl-link" type="button" title="查看计划详情">YSJH-20260822-0008</button>
</td>
<td class="td-plan" rowspan="2"><span class="pl-tag success">已安排</span></td>
<td class="td-plan" rowspan="2">2026-08-22</td>
<td class="td-plan" rowspan="2">出库单</td>
<td class="td-plan" rowspan="2">皖A·12345</td>
<td class="td-plan" rowspan="2">张三</td>
<td class="td-stop"><span class="stop-tag load">装货</span></td>
<td class="td-stop td-left">
<span class="customer">安庆市山峡化工有限公司</span><span class="internal">内部</span>
</td>
<td class="td-stop td-left">
<div class="addr-block">
<div class="addr">安徽省安庆市大观区…</div>
<div class="time">08-22 08:00</div>
</div>
</td>
<td class="td-stop td-left">
<div class="product-stack">
<div>工业硫酸 <span class="pl-muted">98%</span></div>
<div>液碱 <span class="pl-muted">32%</span></div>
</div>
</td>
<td class="td-stop">
<div class="product-stack" style="text-align:center">
<div><span class="qty">80</span></div>
<div><span class="qty">100</span></div>
</div>
</td>
<td class="td-stop"><span class="pl-tag success" style="font-size:11px">出库</span></td>
</tr>
<tr class="row-delivery plan-end">
<td class="td-stop"><span class="stop-tag delivery">送货 #1</span></td>
<td class="td-stop td-left">
<span class="customer">安徽某某化工有限公司</span>
</td>
<td class="td-stop td-left">
<div class="addr-block">
<div class="addr">合肥市蜀山区…</div>
<div class="time">08-22 14:00</div>
</div>
</td>
<td class="td-stop td-left">
<div class="product-stack">
<div>工业硫酸 <span class="pl-muted">98%</span></div>
<div>液碱 <span class="pl-muted">32%</span></div>
</div>
</td>
<td class="td-stop">
<div class="product-stack" style="text-align:center">
<div><span class="qty">80</span></div>
<div><span class="qty">100</span></div>
</div>
</td>
<td class="td-stop"><span class="pl-muted">—</span></td>
</tr>
<!-- 计划 2:1装 + 2送 → rowspan=3 -->
<tr class="row-load">
<td class="td-plan" rowspan="3">2</td>
<td class="td-plan" rowspan="3">
<button class="pl-link" type="button" title="查看计划详情">YSJH-20260815-0012</button>
</td>
<td class="td-plan" rowspan="3"><span class="pl-tag success">已归档</span></td>
<td class="td-plan" rowspan="3">2026-08-15</td>
<td class="td-plan" rowspan="3">出库单</td>
<td class="td-plan" rowspan="3">皖A·67890</td>
<td class="td-plan" rowspan="3">李四</td>
<td class="td-stop"><span class="stop-tag load">装货</span></td>
<td class="td-stop td-left">
<span class="customer">安庆市山峡化工有限公司</span><span class="internal">内部</span>
</td>
<td class="td-stop td-left">
<div class="addr-block">
<div class="addr">安徽省安庆市大观区…</div>
<div class="time">08-15 08:30</div>
</div>
</td>
<td class="td-stop td-left">
<div class="product-stack">
<div>工业硫酸 <span class="pl-muted">98%</span></div>
<div>盐酸 <span class="pl-muted">31%</span></div>
</div>
</td>
<td class="td-stop">
<div class="product-stack" style="text-align:center">
<div><span class="qty">80</span></div>
<div><span class="qty">50</span></div>
</div>
</td>
<td class="td-stop"><span class="pl-tag success" style="font-size:11px">出库</span></td>
</tr>
<tr class="row-delivery">
<td class="td-stop"><span class="stop-tag delivery">送货 #1</span></td>
<td class="td-stop td-left">
<span class="customer">安徽某某化工有限公司</span>
</td>
<td class="td-stop td-left">
<div class="addr-block">
<div class="addr">合肥市蜀山区…</div>
<div class="time">08-15 14:00</div>
</div>
</td>
<td class="td-stop td-left">工业硫酸 <span class="pl-muted">98%</span></td>
<td class="td-stop"><span class="qty">40</span></td>
<td class="td-stop"><span class="pl-muted">—</span></td>
</tr>
<tr class="row-delivery plan-end">
<td class="td-stop"><span class="stop-tag delivery">送货 #2</span></td>
<td class="td-stop td-left">
<span class="customer">安徽某某化工有限公司</span>
</td>
<td class="td-stop td-left">
<div class="addr-block">
<div class="addr">芜湖市镜湖区…</div>
<div class="time">08-15 17:00</div>
</div>
</td>
<td class="td-stop td-left">
<div class="product-stack">
<div>工业硫酸 <span class="pl-muted">98%</span></div>
<div>盐酸 <span class="pl-muted">31%</span></div>
</div>
</td>
<td class="td-stop">
<div class="product-stack" style="text-align:center">
<div><span class="qty">40</span></div>
<div><span class="qty">50</span></div>
</div>
</td>
<td class="td-stop"><span class="pl-muted">—</span></td>
</tr>
</tbody>
</table>
</div>
<div class="hint-bar">
列表结构与 <code>/#/pl/plan</code> 一致:左侧计划主信息 rowspan 合并,右侧装货/送货各占一行;点击计划编号打开查看详情(与列表主标识列链接一致)。
</div>
</div>
<div class="tab-panel" id="panel-payment" role="tabpanel">
<div class="empty">回款记录(本 Demo 不展开,保持现有能力)</div>
</div>
<div class="tab-panel" id="panel-invoice" role="tabpanel">
<div class="empty">开票记录(本 Demo 不展开)</div>
</div>
<div class="tab-panel" id="panel-approval" role="tabpanel">
<div class="empty">审批流程(本 Demo 不展开)</div>
</div>
<div class="tab-panel" id="panel-log" role="tabpanel">
<div class="empty">操作日志(本 Demo 不展开)</div>
</div>
</div>
</div>
<div class="legend">
<span><i class="swatch"></i> 新增安排数量列(表头浅绿底 + 绿色字)</span>
<span>原有金额列保持默认正文色</span>
</div>
</div>
<script>
(function () {
var tabs = document.querySelectorAll('.tab');
var panels = {
contract: document.getElementById('panel-contract'),
plans: document.getElementById('panel-plans'),
payment: document.getElementById('panel-payment'),
invoice: document.getElementById('panel-invoice'),
approval: document.getElementById('panel-approval'),
log: document.getElementById('panel-log')
};
tabs.forEach(function (tab) {
tab.addEventListener('click', function () {
var key = tab.getAttribute('data-tab');
tabs.forEach(function (t) { t.classList.remove('active'); });
tab.classList.add('active');
Object.keys(panels).forEach(function (k) {
panels[k].classList.toggle('active', k === key);
});
});
});
})();
</script>
</body>
</html>