Files
zkxw/mobile-ui/zkxw-mobile-oa-protocol-sample-pay-beautify-demo.html
T
2026-10-15 23:21:07 +08:00

1145 lines
50 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, maximum-scale=1" />
<title>协议单 · 样本运输 &amp; 缴费明细 美化 Demo</title>
<style>
:root {
--brand: #0a9f6d;
--brand-dark: #087f57;
--brand-soft: #e9f9f2;
--brand-mid: #b8ebd4;
--barley: #d6a343;
--barley-soft: #fff7e8;
--text: #1f2a26;
--muted: #6b7b74;
--border: #dcebe4;
--page: #f3f7f5;
--surface: #fff;
--danger: #d14343;
--warn: #cf8a19;
--info: #3b82f6;
--shadow: 0 10px 28px rgba(15, 42, 34, 0.07);
--r16: 16px;
--r12: 12px;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: "PingFang SC", "Hiragino Sans GB", "Noto Sans SC", -apple-system, system-ui, sans-serif;
color: var(--text);
background:
radial-gradient(800px 380px at 10% -10%, rgba(10,159,109,.14), transparent 55%),
radial-gradient(640px 320px at 95% 0%, rgba(214,163,67,.1), transparent 50%),
#f6f8fa;
line-height: 1.45;
}
.stage { max-width: 1360px; margin: 0 auto; padding: 28px 16px 80px; }
.hero h1 { margin: 0 0 8px; font-size: 24px; font-weight: 740; letter-spacing: -0.02em; }
.hero p { margin: 0; max-width: 920px; color: #64748b; font-size: 14px; }
.hero .chips { margin-top: 12px; display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
padding: 6px 12px; border-radius: 999px; font-size: 12px; font-weight: 650;
background: #fff; border: 1px solid #e2e8f0; color: #475569;
}
.chip strong { color: var(--brand-dark); }
.goals {
margin: 18px 0 0;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 10px;
}
.goal {
background: #fff; border: 1px solid #bbf7d0; border-radius: 12px;
padding: 12px 14px; font-size: 12px; color: #14532d;
}
.goal b { color: var(--brand-dark); display: block; margin-bottom: 4px; font-size: 13px; }
.tabs { display: flex; flex-wrap: wrap; gap: 10px; margin: 22px 0 16px; }
.tab {
appearance: none; border: 1px solid #e2e8f0; background: #fff;
border-radius: 999px; padding: 10px 16px; font-size: 13px; font-weight: 650;
color: #475569; cursor: pointer;
}
.tab.is-active {
color: var(--brand-dark); border-color: var(--brand); background: var(--brand-soft);
box-shadow: 0 0 0 3px rgba(10,159,109,.16);
}
.layout {
display: grid;
grid-template-columns: minmax(270px, 340px) 1fr;
gap: 20px; align-items: start;
}
@media (max-width: 980px) { .layout { grid-template-columns: 1fr; } }
.side {
position: sticky; top: 14px;
background: rgba(255,255,255,.94); border: 1px solid #e2e8f0;
border-radius: 18px; padding: 18px; box-shadow: 0 10px 28px rgba(15,23,42,.05);
}
.side h2 { margin: 0 0 4px; font-size: 16px; }
.side .sub { margin: 0 0 12px; font-size: 12px; color: #64748b; }
.side ol { margin: 0; padding-left: 18px; font-size: 13px; color: #475569; }
.side li { margin: 0 0 8px; }
.side li strong { color: var(--brand-dark); }
.phones {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(320px, 390px));
gap: 18px; justify-content: start;
}
.phone-wrap { display: grid; gap: 8px; }
.phone-label { display: flex; justify-content: space-between; align-items: center; padding: 0 4px; }
.phone-label h3 { margin: 0; font-size: 15px; font-weight: 720; }
.tag {
font-size: 11px; font-weight: 750; padding: 4px 8px; border-radius: 999px;
background: var(--brand-soft); color: var(--brand-dark);
}
.tag.muted { background: #f1f5f9; color: #64748b; }
.phone {
width: 100%; max-width: 390px; height: 820px;
border-radius: 36px; border: 10px solid #0f172a;
background: var(--page); overflow: hidden; position: relative;
box-shadow: 0 24px 60px rgba(15,23,42,.18);
display: flex; flex-direction: column;
}
.phone::before {
content: ""; position: absolute; top: 8px; left: 50%; transform: translateX(-50%);
width: 108px; height: 22px; border-radius: 12px; background: #0f172a; z-index: 6;
}
.scroll { flex: 1; overflow: auto; padding: 40px 0 20px; }
/* —— 通用分区壳 —— */
.block {
margin: 0 12px 12px;
background: var(--surface);
border-radius: var(--r16);
border: 1px solid rgba(220,235,228,.9);
box-shadow: var(--shadow);
overflow: hidden;
}
.block__head {
display: flex; align-items: flex-start; justify-content: space-between; gap: 10px;
padding: 14px 14px 0;
}
.block__title-wrap { min-width: 0; }
.block__title {
margin: 0; font-size: 16px; font-weight: 760;
display: flex; align-items: center; gap: 8px;
}
.block__title .ico {
width: 28px; height: 28px; border-radius: 10px;
display: grid; place-items: center; font-size: 14px;
background: linear-gradient(145deg, #12b981, #087f57); color: #fff;
box-shadow: 0 4px 10px rgba(10,159,109,.28);
}
.block__hint { margin: 4px 0 0; font-size: 11px; color: var(--muted); }
/* ========== 样本运输 ========== */
.sum-strip {
margin: 12px 14px 0;
display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px;
}
.sum-item {
padding: 10px 8px; border-radius: 12px; text-align: center;
background: linear-gradient(180deg, #f8fffc, #f2faf6);
border: 1px solid #e3f0ea;
}
.sum-item .k { display: block; font-size: 11px; color: var(--muted); }
.sum-item .v { display: block; margin-top: 2px; font-size: 15px; font-weight: 780; color: var(--brand-dark); }
.sum-item.warn .v { color: #92400e; }
.ops {
margin: 12px 14px 0;
display: flex; gap: 8px; flex-wrap: wrap;
}
.ops .btn {
min-height: 28px; padding: 0 10px; border-radius: 999px;
border: 0; background: var(--brand);
font-size: 11px; font-weight: 700; color: #fff; cursor: pointer;
box-shadow: 0 2px 6px rgba(10,159,109,.18);
}
.ops .btn.primary {
background: linear-gradient(135deg, #12b981, #087f57);
box-shadow: 0 3px 8px rgba(10,159,109,.28);
}
.ops .btn.secondary {
background: #5f8f7d;
box-shadow: 0 2px 6px rgba(15,42,34,.12);
}
.ops .btn.warn {
background: linear-gradient(135deg, #e5a63a, #cf8a19);
box-shadow: 0 2px 6px rgba(207,138,25,.25);
}
.ops .btn:disabled { opacity: .45; }
.sel-bar {
margin: 10px 14px 0;
display: flex; align-items: center; justify-content: space-between;
padding: 8px 12px; border-radius: 12px;
background: #ecfdf5; border: 1px solid var(--brand-mid);
font-size: 12px; font-weight: 650; color: var(--brand-dark);
}
.sel-bar .link { color: var(--brand); text-decoration: underline; cursor: pointer; }
.sample-list { padding: 12px 14px 14px; display: grid; gap: 10px; }
.scard {
position: relative;
border-radius: 14px;
border: 1.5px solid #e3f0ea;
background: #fff;
padding: 12px;
transition: border-color .15s, box-shadow .15s;
}
.scard.is-checked {
border-color: var(--brand);
background: linear-gradient(180deg, #f7fffb, #fff);
box-shadow: 0 0 0 3px rgba(10,159,109,.12);
}
.scard.is-alert {
border-color: #f0c989;
background: linear-gradient(180deg, #fffbeb, #fff);
}
.scard__top {
display: flex; align-items: flex-start; gap: 10px;
}
.check {
width: 22px; height: 22px; border-radius: 7px; flex: none; margin-top: 1px;
border: 2px solid #c5ddd2; display: grid; place-items: center;
font-size: 12px; color: transparent; background: #fff;
}
.scard.is-checked .check {
border-color: var(--brand); background: var(--brand); color: #fff;
}
.scard__main { flex: 1; min-width: 0; }
.scard__code-row {
display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
.scard__code { font-size: 14px; font-weight: 760; letter-spacing: .01em; }
.pill {
flex: none; font-size: 11px; font-weight: 750; padding: 3px 8px; border-radius: 999px;
}
.pill.ok { background: var(--brand-soft); color: var(--brand-dark); }
.pill.warn { background: #fff7e8; color: #b45309; }
.pill.muted { background: #f1f5f9; color: #64748b; }
.pill.danger { background: #fef2f2; color: #b91c1c; }
.type-row {
margin-top: 6px;
display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.type-badge {
display: inline-flex; align-items: center; gap: 4px;
padding: 3px 8px; border-radius: 8px;
background: #f0f7f4; color: #3d524a; font-size: 12px; font-weight: 650;
}
.special {
font-size: 11px; font-weight: 750; color: #b45309;
padding: 2px 6px; border-radius: 6px; background: #fff7e8;
}
.metric-grid {
margin-top: 10px;
display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
}
.metric {
padding: 8px 10px; border-radius: 10px; background: #f6faf8;
border: 1px solid #e8f2ed;
}
.metric .k { display: block; font-size: 11px; color: var(--muted); }
.metric .v { display: block; margin-top: 2px; font-size: 13px; font-weight: 720; }
.metric .v.muted { color: #94a3b8; font-weight: 600; }
.metric .v.money { color: var(--brand-dark); }
.metric.span2 { grid-column: 1 / -1; }
.freight-chip {
display: flex; align-items: center; gap: 6px;
margin-top: 8px; padding: 8px 10px; border-radius: 10px;
background: #f8fffc; border: 1px dashed var(--brand-mid);
font-size: 12px; color: var(--brand-dark); font-weight: 650;
}
.freight-chip.none {
background: #fffaf0; border-color: #f0e0bc; color: #92400e;
}
.freight-chip .dot {
width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none;
}
.scard__foot {
margin-top: 10px; display: flex; gap: 8px; justify-content: flex-end;
}
.mini {
min-height: 26px; padding: 0 10px; border-radius: 999px;
border: 0; background: var(--brand);
font-size: 11px; font-weight: 700; color: #fff; cursor: pointer;
box-shadow: 0 2px 5px rgba(10,159,109,.16);
}
.mini.ghost,
.mini.secondary {
background: #5f8f7d;
box-shadow: 0 2px 5px rgba(15,42,34,.12);
}
.mini.danger {
background: linear-gradient(135deg, #e35d5d, #d14343);
box-shadow: 0 2px 5px rgba(209,67,67,.2);
}
.mini.warn {
background: linear-gradient(135deg, #e5a63a, #cf8a19);
box-shadow: 0 2px 5px rgba(207,138,25,.22);
}
.mini.primary {
background: linear-gradient(135deg, #12b981, #087f57);
box-shadow: 0 2px 6px rgba(10,159,109,.28);
}
.empty {
margin: 8px 14px 16px; padding: 28px 16px; text-align: center;
border-radius: 14px; border: 1.5px dashed #b8ebd4; background: #f7fffb;
}
.empty .big { font-size: 28px; margin-bottom: 6px; }
.empty p { margin: 0 0 12px; font-size: 13px; color: var(--muted); }
.empty .btn {
min-height: 30px; padding: 0 14px; border-radius: 999px; border: 0;
background: linear-gradient(135deg, #12b981, #087f57);
color: #fff; font-weight: 720; font-size: 12px;
box-shadow: 0 3px 8px rgba(10,159,109,.25);
}
/* ========== 缴费 ========== */
.pay-sum {
margin: 12px 14px 0;
padding: 12px;
border-radius: 14px;
background: linear-gradient(135deg, #ecfdf5, #fff7e8 70%);
border: 1px solid #e5efdf;
display: grid; gap: 8px;
}
.pay-sum__row {
display: flex; justify-content: space-between; align-items: baseline;
font-size: 12px; color: #5b6b64;
}
.pay-sum__row strong { font-size: 18px; color: var(--brand-dark); font-weight: 800; }
.pay-sum__row .amt { font-weight: 760; color: #92400e; }
.progress {
height: 8px; border-radius: 999px; background: rgba(255,255,255,.7);
overflow: hidden; border: 1px solid rgba(10,159,109,.12);
}
.progress > i {
display: block; height: 100%; width: 42%;
background: linear-gradient(90deg, #12b981, #087f57);
border-radius: inherit;
}
.pay-card {
margin: 12px 14px;
border-radius: 14px;
border: 1px solid #e3f0ea;
background: #fff;
overflow: hidden;
}
.pay-card__head {
display: flex; align-items: center; justify-content: space-between; gap: 8px;
padding: 12px 12px 10px;
background: linear-gradient(90deg, #f3fbf7, #fff 55%);
border-bottom: 1px solid #eef6f2;
}
.pay-card__head strong { font-size: 14px; font-weight: 760; }
.pay-card__head .code { font-size: 11px; color: var(--muted); font-weight: 650; }
.pay-card__body { padding: 12px; display: grid; gap: 12px; }
.seg3 {
display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px;
padding: 4px; border-radius: 12px; background: #eef6f2;
}
.seg3 button {
min-height: 36px; border: 0; border-radius: 9px;
background: transparent; color: var(--muted);
font-size: 12px; font-weight: 720; cursor: pointer;
}
.seg3 button.on {
background: #fff; color: var(--brand-dark);
box-shadow: 0 2px 8px rgba(15,42,34,.08);
}
.field { display: grid; gap: 6px; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.label { font-size: 12px; font-weight: 680; color: #3d524a; }
.ctl {
min-height: 42px; border-radius: 11px; padding: 0 12px;
background: #f4faf7; border: 1px solid transparent;
display: flex; align-items: center; justify-content: space-between;
font-size: 14px; color: var(--text); font-weight: 600;
}
.ctl .ph { color: #94a3b8; font-weight: 500; }
.ctl .chev { color: #9cb0a7; }
/* 分期时间线 */
.sch-head {
display: flex; align-items: center; justify-content: space-between;
margin-top: 2px;
}
.sch-head h5 {
margin: 0; font-size: 13px; font-weight: 760; color: var(--text);
display: flex; align-items: center; gap: 6px;
}
.sch-head h5::before {
content: ""; width: 6px; height: 6px; border-radius: 50%;
background: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft);
}
.sch-head .hint { font-size: 11px; color: var(--muted); }
.timeline { display: grid; gap: 0; position: relative; }
.titem {
position: relative;
padding: 0 0 12px 22px;
}
.titem:last-child { padding-bottom: 0; }
.titem::before {
content: ""; position: absolute; left: 7px; top: 18px; bottom: 0;
width: 2px; background: #d8eee4;
}
.titem:last-child::before { display: none; }
.titem__dot {
position: absolute; left: 0; top: 12px;
width: 16px; height: 16px; border-radius: 50%;
background: #fff; border: 2px solid var(--brand);
display: grid; place-items: center;
font-size: 9px; font-weight: 800; color: var(--brand-dark);
z-index: 1;
}
.titem.is-paid .titem__dot {
background: var(--brand); border-color: var(--brand); color: #fff;
}
.titem.is-overdue .titem__dot {
border-color: var(--danger); color: var(--danger);
}
.titem.is-overdue::before { background: #fecaca; }
.tbox {
border-radius: 12px; border: 1px solid #e3f0ea; background: #fafdfb;
overflow: hidden;
}
.tbox.is-open { border-color: var(--brand-mid); background: #fff; box-shadow: 0 4px 14px rgba(10,159,109,.08); }
.tbox__summary {
display: grid; grid-template-columns: 1fr auto; gap: 4px 10px;
padding: 10px 12px; cursor: pointer; align-items: center;
}
.tbox__summary .period { font-size: 13px; font-weight: 760; }
.tbox__summary .due { font-size: 11px; color: var(--muted); grid-column: 1; }
.tbox__summary .amt {
grid-row: 1 / 3; grid-column: 2; align-self: center; text-align: right;
font-size: 15px; font-weight: 800; color: var(--brand-dark);
}
.tbox__summary .chev {
grid-column: 2; justify-self: end; font-size: 11px; color: var(--muted);
}
.tbox__body {
display: none;
padding: 0 12px 12px;
border-top: 1px dashed #e3f0ea;
}
.tbox.is-open .tbox__body { display: grid; gap: 10px; padding-top: 12px; }
.stat-row {
display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
}
.stat {
padding: 8px 10px; border-radius: 10px; background: #f4faf7;
font-size: 11px; color: var(--muted);
}
.stat b { display: block; margin-top: 2px; font-size: 14px; color: var(--text); }
.stat.arrears b { color: #b45309; }
.stat.paid b { color: var(--brand-dark); }
.transfer {
border-radius: 12px;
border: 1px solid #e8f0ec;
background: linear-gradient(180deg, #f8fffc, #fff);
padding: 10px;
display: grid; gap: 8px;
}
.transfer__top {
display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
.transfer__top strong { font-size: 13px; }
.transfer__grid {
display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
}
.transfer .mini-field .k { font-size: 11px; color: var(--muted); }
.transfer .mini-field .v { font-size: 13px; font-weight: 700; margin-top: 2px; }
.voucher {
display: flex; align-items: center; gap: 8px;
padding: 8px; border-radius: 10px; background: #f4faf7;
border: 1px dashed #b8ebd4; font-size: 12px; color: var(--brand-dark); font-weight: 650;
}
.voucher .thumb {
width: 36px; height: 36px; border-radius: 8px;
background: linear-gradient(135deg, #d1fae5, #a7f3d0);
flex: none;
}
.transfer__actions {
display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end;
}
.add-transfer {
min-height: 28px; width: 100%;
border-radius: 999px; border: 0;
background: linear-gradient(135deg, #12b981, #087f57);
color: #fff;
font-size: 11px; font-weight: 720; cursor: pointer;
box-shadow: 0 3px 8px rgba(10,159,109,.22);
}
/* 现状对照简版 */
.old .block { box-shadow: none; border-radius: 16px; }
.old-card {
margin: 10px 12px; padding: 12px; border: 1px solid #e2e8f0; border-radius: 12px; background: #fff;
}
.old-card h4 { margin: 0 0 8px; font-size: 14px; }
.old-meta { display: flex; flex-wrap: wrap; gap: 8px 12px; font-size: 12px; color: #64748b; }
.old-actions { margin-top: 10px; display: flex; gap: 8px; }
.old-cell {
margin: 0 12px 8px; padding: 10px 12px; background: #f7f8fa; border-radius: 8px;
font-size: 13px; color: #475569;
display: flex; justify-content: space-between;
}
.old-toolbar {
margin: 8px 12px 0; display: flex; flex-wrap: wrap; gap: 6px;
}
.old-toolbar button {
min-height: 26px; padding: 0 10px; border-radius: 999px;
border: 0; background: var(--brand); color: #fff; font-size: 11px; font-weight: 700;
}
.note {
margin-top: 18px; padding: 14px 16px; border-radius: 14px;
background: #fff; border: 1px solid #e2e8f0; font-size: 13px; color: #475569;
}
.note code {
font-size: 12px; padding: 2px 6px; border-radius: 6px; background: #f1f5f9; color: #0f766e;
}
</style>
</head>
<body>
<div class="stage">
<header class="hero">
<h1>样本运输 · 缴费明细 — 好与美观专项</h1>
<p>
针对销售专员 / 地区经理协议单中最复杂的两块:
<strong>样本及运输</strong>(多样本勾选、运费批次、ETA)与
<strong>缴费明细</strong>(趸交/分期、应缴批次、转账凭证)。
字段与现网一致,重点优化信息层级、批量操作与分期扫读。
</p>
<div class="chips">
<span class="chip"><strong>对齐</strong> ProtocolSampleTransportPanel</span>
<span class="chip"><strong>对齐</strong> ProtocolSamplePaymentPanel(V2)</span>
<span class="chip"><strong>Token</strong> #0a9f6d</span>
</div>
<div class="goals">
<div class="goal"><b>样本:一眼状态</b>类型 / 价格 / 运费 / ETA 分区展示,未配运费醒目提醒</div>
<div class="goal"><b>样本:好勾好配</b>勾选态强化 + 已选条;操作统一小实心按钮</div>
<div class="goal"><b>缴费:分期可读</b>时间线折叠,默认看期次金额,展开再录转账</div>
<div class="goal"><b>缴费:缴清进度</b>顶部合计 + 已缴/欠缴进度条,减少翻找</div>
</div>
</header>
<div class="tabs" role="tablist">
<button type="button" class="tab is-active" data-tab="sample">① 样本及运输</button>
<button type="button" class="tab" data-tab="pay">② 缴费明细</button>
<button type="button" class="tab" data-tab="compare">③ 现状对照</button>
</div>
<div class="layout">
<aside class="side" id="side">
<h2>样本及运输 · 设计要点</h2>
<p class="sub">列表卡片化,批量运费操作更清晰</p>
<ol id="side-list">
<li><strong>顶部汇总条</strong>:样本数 / 优惠价合计 / 待配运费数</li>
<li><strong>实心小按钮</strong>:工具栏 / 卡片操作统一实心,高度约 26–28px</li>
<li><strong>已选提示条</strong>:勾选后出现,提示可配置运费</li>
<li><strong>指标双列</strong>:优惠价、存储年限、ETA 分区,忌纯文字堆砌</li>
<li><strong>运费芯片</strong>:已配置绿虚线;未配置琥珀提醒</li>
<li><strong>特殊样本</strong>:独立琥珀角标,不淹没在备注里</li>
</ol>
</aside>
<div class="phones">
<!-- ===== 样本运输(美化) ===== -->
<div class="phone-wrap" data-view="sample">
<div class="phone-label"><h3>样本及运输 · 推荐</h3><span class="tag">好用优先</span></div>
<div class="phone">
<div class="scroll">
<section class="block">
<div class="block__head">
<div class="block__title-wrap">
<h3 class="block__title"><span class="ico">样</span>样本及运输</h3>
<p class="block__hint">勾选样本后可批量配置 / 取消运费</p>
</div>
</div>
<div class="sum-strip">
<div class="sum-item"><span class="k">样本</span><span class="v">2</span></div>
<div class="sum-item"><span class="k">优惠价合计</span><span class="v">¥11.6万</span></div>
<div class="sum-item warn"><span class="k">待配运费</span><span class="v">1</span></div>
</div>
<div class="ops">
<button type="button" class="btn primary">+ 添加样本</button>
<button type="button" class="btn secondary">配置运费</button>
<button type="button" class="btn warn">取消运费</button>
</div>
<div class="sel-bar">
<span>已选 1 个样本</span>
<span class="link">去配置运费 ›</span>
</div>
<div class="sample-list">
<!-- 已配运费 + 勾选 -->
<article class="scard is-checked">
<div class="scard__top">
<span class="check">✓</span>
<div class="scard__main">
<div class="scard__code-row">
<span class="scard__code">YB20261015001</span>
<span class="pill ok">已采集</span>
</div>
<div class="type-row">
<span class="type-badge">🩸 脐带血</span>
<span class="special">特殊 · HBV</span>
</div>
<div class="metric-grid">
<div class="metric">
<span class="k">优惠价</span>
<span class="v money">¥68,000</span>
</div>
<div class="metric">
<span class="k">存储年限</span>
<span class="v">20 年</span>
</div>
<div class="metric span2">
<span class="k">预计到达</span>
<span class="v">2026-10-18 14:00</span>
</div>
</div>
<div class="freight-chip">
<span class="dot"></span>
顺丰速运 · ¥120(本批共用)
</div>
</div>
</div>
<div class="scard__foot">
<button type="button" class="mini secondary">编辑</button>
<button type="button" class="mini danger">删除</button>
</div>
</article>
<!-- 未配运费 -->
<article class="scard is-alert">
<div class="scard__top">
<span class="check"></span>
<div class="scard__main">
<div class="scard__code-row">
<span class="scard__code">YB20261015002</span>
<span class="pill warn">检测中</span>
</div>
<div class="type-row">
<span class="type-badge">🧬 脐带间充质</span>
</div>
<div class="metric-grid">
<div class="metric">
<span class="k">优惠价</span>
<span class="v money">¥48,000</span>
</div>
<div class="metric">
<span class="k">存储年限</span>
<span class="v">15 年</span>
</div>
<div class="metric span2">
<span class="k">预计到达</span>
<span class="v muted">未填写</span>
</div>
</div>
<div class="freight-chip none">
<span class="dot"></span>
未配置运费 — 勾选后点「配置运费」
</div>
</div>
</div>
<div class="scard__foot">
<button type="button" class="mini secondary">编辑</button>
<button type="button" class="mini danger">删除</button>
</div>
</article>
</div>
</section>
<!-- 空状态示意(缩略) -->
<section class="block" style="opacity:.92">
<div class="block__head">
<div class="block__title-wrap">
<h3 class="block__title"><span class="ico">空</span>空状态参考</h3>
<p class="block__hint">无样本时引导添加,避免冰冷 Empty</p>
</div>
</div>
<div class="empty">
<div class="big">📦</div>
<p>还没有样本,添加后可配置运输与缴费</p>
<button type="button" class="btn">添加第一个样本</button>
</div>
</section>
</div>
</div>
</div>
<!-- 样本:编辑弹层示意 -->
<div class="phone-wrap" data-view="sample">
<div class="phone-label"><h3>添加/编辑样本 · 底部弹层</h3><span class="tag">交互</span></div>
<div class="phone" style="background:#1f2a26">
<div class="scroll" style="padding-top:120px; background:rgba(0,0,0,.35)">
<div style="margin:0 0 0; background:#fff; border-radius:20px 20px 0 0; min-height:620px; padding:8px 0 24px;">
<div style="width:40px;height:4px;border-radius:999px;background:#e2e8f0;margin:8px auto 12px;"></div>
<h3 style="margin:0 16px 4px;font-size:17px;font-weight:760;">编辑样本</h3>
<p style="margin:0 16px 14px;font-size:12px;color:#6b7b74;">保存后编码不可随意变更</p>
<div style="padding:0 16px;display:grid;gap:12px;">
<div class="field">
<div class="label">样本类型 *</div>
<div class="ctl">脐带血 <span class="chev">›</span></div>
</div>
<div class="field">
<div class="label">样本编码</div>
<div class="ctl"><span class="ph">保存后自动生成</span></div>
</div>
<div class="field-row">
<div class="field">
<div class="label">原价格</div>
<div class="ctl"><span class="ph">¥72,000</span></div>
</div>
<div class="field">
<div class="label">优惠价 *</div>
<div class="ctl">68000</div>
</div>
</div>
<div class="field-row">
<div class="field">
<div class="label">存储年限</div>
<div class="ctl">20</div>
</div>
<div class="field">
<div class="label">样本状态</div>
<div class="ctl">已采集 <span class="chev">›</span></div>
</div>
</div>
<div class="field">
<div class="label">预计到达时间</div>
<div class="ctl">2026-10-18 14:00 <span class="chev">›</span></div>
</div>
<div style="display:flex;align-items:center;justify-content:space-between;padding:10px 12px;border-radius:12px;background:#fff7e8;border:1px solid #f0e0bc;">
<div>
<div style="font-size:13px;font-weight:720;">特殊样本</div>
<div style="font-size:11px;color:#92400e;margin-top:2px;">开启后须填写特殊说明</div>
</div>
<div style="width:44px;height:26px;border-radius:999px;background:#0a9f6d;position:relative;">
<i style="position:absolute;right:3px;top:3px;width:20px;height:20px;border-radius:50%;background:#fff;"></i>
</div>
</div>
<div class="field">
<div class="label">特殊说明</div>
<div class="ctl" style="min-height:64px;align-items:flex-start;padding-top:10px;">HBV 携带,入库加急</div>
</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:8px;">
<button type="button" class="mini secondary" style="min-height:36px;border-radius:10px;font-size:13px;">取消</button>
<button type="button" class="mini primary" style="min-height:36px;border-radius:10px;font-size:13px;">确定</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- ===== 缴费明细 ===== -->
<div class="phone-wrap" data-view="pay" hidden>
<div class="phone-label"><h3>缴费明细 · 推荐</h3><span class="tag">分期时间线</span></div>
<div class="phone">
<div class="scroll">
<section class="block">
<div class="block__head">
<div class="block__title-wrap">
<h3 class="block__title"><span class="ico">缴</span>缴费信息</h3>
<p class="block__hint">按样本配置方案;应缴批次自动生成,可微调</p>
</div>
</div>
<div class="pay-sum">
<div class="pay-sum__row">
<span>合同合计</span>
<strong>¥116,000</strong>
</div>
<div class="pay-sum__row">
<span>已缴 ¥28,000 · 欠缴</span>
<span class="amt">¥88,000</span>
</div>
<div class="progress"><i></i></div>
</div>
<!-- 样本1 分期 -->
<article class="pay-card">
<div class="pay-card__head">
<div>
<strong>脐带血</strong>
<div class="code">YB20261015001</div>
</div>
<span class="pill ok">分期 · 3 期</span>
</div>
<div class="pay-card__body">
<div>
<div class="label" style="margin-bottom:6px;">缴费模式</div>
<div class="seg3">
<button type="button">趸交</button>
<button type="button" class="on">分期</button>
<button type="button">固定比例</button>
</div>
</div>
<div class="field">
<div class="label">样本合同金额</div>
<div class="ctl">68000</div>
</div>
<div class="field-row">
<div class="field">
<div class="label">期数</div>
<div class="ctl">3</div>
</div>
<div class="field">
<div class="label">间隔(月)</div>
<div class="ctl">3</div>
</div>
</div>
<div class="field-row">
<div class="field">
<div class="label">开始时间</div>
<div class="ctl">2026-10-20 <span class="chev">›</span></div>
</div>
<div class="field">
<div class="label">催缴预警(天)</div>
<div class="ctl">7</div>
</div>
</div>
<div class="sch-head">
<h5>应缴批次</h5>
<span class="hint">点开录入转账</span>
</div>
<div class="timeline">
<!-- 第1期 已缴 展开 -->
<div class="titem is-paid">
<div class="titem__dot">✓</div>
<div class="tbox is-open">
<div class="tbox__summary">
<span class="period">第 1 期</span>
<span class="amt">¥28,000</span>
<span class="due">应缴 2026-10-20 · 已结清</span>
<span class="chev">收起 ▲</span>
</div>
<div class="tbox__body">
<div class="stat-row">
<div class="stat paid"><span>已缴</span><b>¥28,000</b></div>
<div class="stat arrears"><span>欠缴</span><b>¥0</b></div>
</div>
<article class="transfer">
<div class="transfer__top">
<strong>转账 1</strong>
<span class="pill ok">财务已确认</span>
</div>
<div class="transfer__grid">
<div class="mini-field"><div class="k">方式</div><div class="v">微信转账</div></div>
<div class="mini-field"><div class="k">金额</div><div class="v">¥28,000</div></div>
<div class="mini-field" style="grid-column:1/-1"><div class="k">时间</div><div class="v">2026-10-15 16:22</div></div>
</div>
<div class="voucher">
<span class="thumb"></span>
转账凭证.jpg · 已上传
</div>
</article>
</div>
</div>
</div>
<!-- 第2期 待缴 折叠 -->
<div class="titem">
<div class="titem__dot">2</div>
<div class="tbox">
<div class="tbox__summary">
<span class="period">第 2 期</span>
<span class="amt">¥20,000</span>
<span class="due">应缴 2027-01-20 · 待缴费</span>
<span class="chev">展开 ▼</span>
</div>
</div>
</div>
<!-- 第3期 -->
<div class="titem">
<div class="titem__dot">3</div>
<div class="tbox">
<div class="tbox__summary">
<span class="period">第 3 期</span>
<span class="amt">¥20,000</span>
<span class="due">应缴 2027-04-20 · 待缴费</span>
<span class="chev">展开 ▼</span>
</div>
</div>
</div>
</div>
</div>
</article>
<!-- 样本2 趸交 + 展开录转账 -->
<article class="pay-card">
<div class="pay-card__head">
<div>
<strong>脐带间充质</strong>
<div class="code">YB20261015002</div>
</div>
<span class="pill warn">趸交</span>
</div>
<div class="pay-card__body">
<div class="seg3">
<button type="button" class="on">趸交</button>
<button type="button">分期</button>
<button type="button">固定比例</button>
</div>
<div class="field-row">
<div class="field">
<div class="label">合同金额</div>
<div class="ctl">48000</div>
</div>
<div class="field">
<div class="label">截止时间</div>
<div class="ctl">2026-11-30 <span class="chev">›</span></div>
</div>
</div>
<div class="sch-head">
<h5>应缴批次</h5>
<span class="hint">1 笔趸交</span>
</div>
<div class="timeline">
<div class="titem is-overdue">
<div class="titem__dot">!</div>
<div class="tbox is-open">
<div class="tbox__summary">
<span class="period">趸交应缴</span>
<span class="amt">¥48,000</span>
<span class="due" style="color:#b91c1c">截止 2026-11-30 · 待登记</span>
<span class="chev">收起 ▲</span>
</div>
<div class="tbox__body">
<div class="stat-row">
<div class="stat paid"><span>已缴</span><b>¥0</b></div>
<div class="stat arrears"><span>欠缴</span><b>¥48,000</b></div>
</div>
<article class="transfer">
<div class="transfer__top">
<strong>转账 1(草稿)</strong>
<span class="pill muted">待保存</span>
</div>
<div class="transfer__grid">
<div class="mini-field">
<div class="k">转账方式</div>
<div class="v" style="color:#94a3b8;font-weight:500">请选择 ›</div>
</div>
<div class="mini-field">
<div class="k">转账金额</div>
<div class="v" style="color:#94a3b8;font-weight:500">请输入</div>
</div>
</div>
<div class="voucher" style="border-style:dashed;">
<span class="thumb" style="background:#e9f9f2;display:grid;place-items:center;color:#0a9f6d;font-size:18px;">+</span>
点击上传转账凭证
</div>
<div class="transfer__actions">
<button type="button" class="mini danger">删除</button>
<button type="button" class="mini secondary">保存</button>
<button type="button" class="mini primary">提交财务</button>
</div>
</article>
<button type="button" class="add-transfer">+ 添加转账</button>
</div>
</div>
</div>
</div>
</div>
</article>
</section>
</div>
</div>
</div>
<!-- ===== 现状对照 ===== -->
<div class="phone-wrap" data-view="compare" hidden>
<div class="phone-label"><h3>现状 · 样本运输</h3><span class="tag muted">AS-IS</span></div>
<div class="phone old">
<div class="scroll" style="padding-top:44px;">
<section class="block">
<div style="padding:16px 16px 0;display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;">
<h2 style="margin:0;padding-left:10px;border-left:3px solid #0a9f6d;font-size:15px;">样本及运输</h2>
</div>
<div class="old-toolbar">
<button type="button">添加样本</button>
<button type="button">配置运费</button>
<button type="button" style="border-color:#cf8a19;color:#cf8a19;">取消运费</button>
</div>
<p style="margin:8px 16px 12px;font-size:12px;color:#64748b;">规则与管理端「样本及运输」一致</p>
<div class="old-card">
<h4>☐ YB20261015001 <span class="pill ok" style="float:right;">已采集</span></h4>
<div class="old-meta">
<span>脐带血</span><span>优惠价 ¥68,000</span>
<span>顺丰 · ¥120(共用)</span><span>ETA 10-18</span>
</div>
<div class="old-actions">
<button type="button" class="mini">编辑</button>
<button type="button" class="mini danger">删除</button>
</div>
</div>
<div class="old-card">
<h4>☐ YB20261015002 <span class="pill warn" style="float:right;">检测中</span></h4>
<div class="old-meta">
<span>脐带间充质</span><span>优惠价 ¥48,000</span>
<span style="color:#94a3b8;">未配置运费</span>
</div>
<div class="old-actions">
<button type="button" class="mini">编辑</button>
<button type="button" class="mini danger">删除</button>
</div>
</div>
</section>
</div>
</div>
</div>
<div class="phone-wrap" data-view="compare" hidden>
<div class="phone-label"><h3>现状 · 缴费明细</h3><span class="tag muted">AS-IS</span></div>
<div class="phone old">
<div class="scroll" style="padding-top:44px;">
<section class="block">
<h2 style="margin:16px 16px 0;padding-left:10px;border-left:3px solid #0a9f6d;font-size:15px;">缴费信息</h2>
<p style="margin:8px 16px 12px;font-size:12px;color:#64748b;">按样本配置缴费方案…</p>
<div style="padding:0 16px 8px;display:flex;justify-content:space-between;">
<strong style="font-size:14px;">脐带血</strong>
<span style="font-size:12px;color:#64748b;">YB20261015001</span>
</div>
<div class="old-cell"><span>缴费模式</span><span>分期 ›</span></div>
<div class="old-cell"><span>样本合同金额</span><span>68000</span></div>
<div class="old-cell"><span>分期期数</span><span>3</span></div>
<div class="old-cell"><span>每期间隔(月)</span><span>3</span></div>
<div style="padding:12px 16px 8px;font-size:13px;font-weight:600;">应缴批次</div>
<div style="margin:0 12px 12px;padding:10px;border:1px solid #e2e8f0;border-radius:8px;background:#fff;">
<div style="color:#0a9f6d;font-size:13px;font-weight:600;margin-bottom:8px;">第 1 期</div>
<div class="old-cell" style="margin:0 0 6px;"><span>应缴费金额</span><span>28000</span></div>
<div class="old-cell" style="margin:0 0 6px;"><span>应缴费时间</span><span>2026-10-20</span></div>
<div style="font-size:12px;color:#64748b;padding:4px 0;">已缴 ¥28000 · 欠缴 ¥0</div>
<div style="border-top:1px solid #e2e8f0;margin-top:8px;padding-top:8px;">
<strong style="font-size:13px;">转账 1</strong>
<div class="old-cell" style="margin:8px 0 0;"><span>转账方式</span><span>微信</span></div>
<div class="old-cell" style="margin:6px 0 0;"><span>转账金额</span><span>28000</span></div>
</div>
</div>
</section>
</div>
</div>
</div>
</div>
</div>
<div class="note">
文件:<code>mobile-ui/zkxw-mobile-oa-protocol-sample-pay-beautify-demo.html</code>
· 总表单 Demo 见 <code>zkxw-mobile-oa-protocol-form-beautify-demo.html</code>。
确认本专项后,优先改
<code>ProtocolSampleTransportPanel.vue</code> /
<code>ProtocolSamplePaymentPanel.vue</code> 的结构与 scoped 样式(不改业务规则)。
</div>
</div>
<script>
const copy = {
sample: {
title: '样本及运输 · 设计要点',
sub: '列表卡片化,批量运费操作更清晰',
items: [
['顶部汇总条', '样本数 / 优惠价合计 / 待配运费数'],
['实心小按钮', '工具栏/卡片操作统一实心,约 26–28px 高'],
['已选提示条', '勾选后出现,引导去配置运费'],
['指标双列', '优惠价、年限、ETA 分区,忌纯文字堆砌'],
['运费芯片', '已配置绿虚线;未配置琥珀提醒'],
['特殊样本', '独立琥珀角标,不淹没在备注里']
]
},
pay: {
title: '缴费明细 · 设计要点',
sub: '分期时间线 + 折叠转账,降低长表压迫感',
items: [
['顶部缴清进度', '合同合计 / 已缴 / 欠缴 + 进度条'],
['模式三段切换', '趸交 / 分期 / 固定比例,一键切换'],
['期次时间线', '左轴圆点:已结清 / 待缴 / 逾期语义色'],
['默认折叠', '摘要看期次+金额+日期;展开再录转账'],
['转账卡片', '方式/金额/凭证/操作同卡,状态 Tag 明确'],
['添加转账', '虚线按钮在期次内,路径短']
]
},
compare: {
title: '现状问题(对照)',
sub: '现网 van-cell 堆叠,信息密度高但层级弱',
items: [
['样本 meta 平铺', '类型/价/运费/ETA 挤一行,扫读难'],
['未配运费不醒目', '灰色小字,易漏配'],
['缴费全展开', '多期 × 多转账 = 超长滚动'],
['缺全局进度', '不知还欠多少,要心算'],
['描边按钮偏大', '操作权重平均,描边样式占地方']
]
}
}
const tabs = document.querySelectorAll('.tab')
const wraps = document.querySelectorAll('.phone-wrap')
const sideTitle = document.querySelector('#side h2')
const sideSub = document.querySelector('#side .sub')
const sideList = document.getElementById('side-list')
function renderSide(key) {
const c = copy[key]
sideTitle.textContent = c.title
sideSub.textContent = c.sub
sideList.innerHTML = c.items.map(([a, b]) => `<li><strong>${a}</strong>:${b}</li>`).join('')
}
function show(tab) {
tabs.forEach((t) => t.classList.toggle('is-active', t.dataset.tab === tab))
wraps.forEach((w) => { w.hidden = w.dataset.view !== tab })
renderSide(tab)
}
tabs.forEach((t) => t.addEventListener('click', () => show(t.dataset.tab)))
// 简易展开交互(缴费时间线)
document.addEventListener('click', (e) => {
const sum = e.target.closest('.tbox__summary')
if (!sum) return
const box = sum.closest('.tbox')
if (!box || !box.querySelector('.tbox__body')) return
box.classList.toggle('is-open')
const chev = sum.querySelector('.chev')
if (chev) chev.textContent = box.classList.contains('is-open') ? '收起 ▲' : '展开 ▼'
})
</script>
</body>
</html>