Files
zkxw/web-admin/demo-payment-confirm-layouts.html
T
2026-06-15 11:43:16 +08:00

1281 lines
39 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>缴退费财务确认 · 布局方案 Demo</title>
<style>
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--primary: #10b981;
--primary-dark: #059669;
--primary-bg: #ecfdf5;
--mint-border: #c5e0d4;
--text: #1e293b;
--muted: #64748b;
--surface: #fff;
--page-bg: #f0f2f5;
--border: #e2e8f0;
--warning: #d97706;
--warning-bg: #fffbeb;
}
body {
font-family:
Inter,
-apple-system,
BlinkMacSystemFont,
'PingFang SC',
'Hiragino Sans GB',
'Microsoft YaHei',
sans-serif;
font-size: 14px;
line-height: 1.5;
color: var(--text);
background: var(--page-bg);
padding: 32px 24px 64px;
}
.page-head {
max-width: 1200px;
margin: 0 auto 28px;
}
.page-head h1 {
font-size: 20px;
font-weight: 600;
margin-bottom: 8px;
}
.page-head p {
color: var(--muted);
max-width: 860px;
line-height: 1.6;
}
.scheme-nav {
max-width: 1200px;
margin: 0 auto 20px;
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.scheme-nav a {
padding: 6px 14px;
border-radius: 999px;
border: 1px solid var(--border);
background: var(--surface);
color: var(--muted);
font-size: 12px;
text-decoration: none;
transition: all 0.15s;
}
.scheme-nav a:hover {
border-color: var(--mint-border);
color: var(--primary-dark);
}
.demo-block {
max-width: 1200px;
margin: 0 auto 32px;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 10px;
overflow: hidden;
box-shadow: 0 1px 3px rgb(15 23 42 / 6%);
}
.demo-label {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 16px;
padding: 14px 20px;
border-bottom: 1px solid var(--border);
background: #fafbfc;
}
.demo-label strong {
font-size: 14px;
font-weight: 600;
display: block;
margin-bottom: 4px;
}
.demo-label .tag-rec {
flex-shrink: 0;
padding: 3px 10px;
border-radius: 999px;
background: var(--primary-bg);
color: var(--primary-dark);
font-size: 11px;
font-weight: 600;
}
.demo-label span {
font-size: 12px;
color: var(--muted);
line-height: 1.5;
}
.panel-shell {
min-height: 480px;
}
/* ── 共用:面板标题 ── */
.panel-top {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 24px;
border-bottom: 1px solid var(--border);
}
.title-bar-heading {
display: flex;
align-items: center;
gap: 8px;
font-size: 16px;
font-weight: 600;
}
.title-bar-heading::before {
content: '';
width: 4px;
height: 14px;
border-radius: 999px;
background: var(--primary-dark);
}
/* ── 共用:胶囊 Tab(缴费/退费) ── */
.type-capsule {
display: inline-flex;
gap: 4px;
padding: 4px;
background: #f1f5f9;
border: 1px solid var(--border);
border-radius: 8px;
}
.type-capsule__btn {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 8px 18px;
border: none;
border-radius: 6px;
background: transparent;
font-size: 13px;
font-weight: 500;
color: var(--muted);
cursor: pointer;
white-space: nowrap;
transition: all 0.15s;
}
.type-capsule__btn:hover:not(.is-active) {
color: var(--text);
background: rgb(255 255 255 / 60%);
}
.type-capsule__btn.is-active {
background: #fff;
color: var(--primary-dark);
box-shadow: 0 1px 3px rgb(15 23 42 / 8%);
font-weight: 600;
}
.type-capsule__badge {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 18px;
height: 18px;
padding: 0 5px;
border-radius: 999px;
background: var(--warning-bg);
color: var(--warning);
font-size: 11px;
font-weight: 600;
}
.type-capsule__btn.is-active .type-capsule__badge {
background: var(--primary-bg);
color: var(--primary-dark);
}
/* ── 共用:筛选区 ── */
.filter-block {
padding: 16px 24px;
border-bottom: 1px solid var(--border);
}
.filter-grid {
display: grid;
grid-template-columns: 1fr 280px;
gap: 12px 16px;
}
.filter-field label {
display: block;
font-size: 11px;
font-weight: 500;
color: var(--muted);
margin-bottom: 4px;
}
.filter-field input,
.filter-field .fake-date {
width: 100%;
height: 36px;
padding: 0 12px;
border: 1px solid var(--border);
border-radius: 8px;
font-size: 14px;
color: var(--text);
background: #fff;
}
.filter-actions-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-top: 12px;
}
.filter-hint {
font-size: 12px;
color: var(--muted);
flex: 1;
min-width: 0;
}
.filter-actions-end {
display: flex;
gap: 8px;
flex-shrink: 0;
}
.btn {
display: inline-flex;
align-items: center;
gap: 6px;
height: 36px;
padding: 0 16px;
border-radius: 8px;
font-size: 14px;
cursor: pointer;
border: 1px solid var(--border);
background: #fff;
color: var(--text);
}
.btn-main {
border-color: var(--primary);
background: var(--primary);
color: #fff;
}
/* ── 共用:Tag ── */
.tag {
display: inline-flex;
align-items: center;
padding: 2px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
}
.tag.warning {
background: var(--warning-bg);
color: var(--warning);
}
.tag.success {
background: var(--primary-bg);
color: var(--primary-dark);
}
.tag.info {
background: #f1f5f9;
color: var(--muted);
}
.tag.muted {
background: #f8fafc;
color: var(--muted);
}
/* ── 共用:确认卡片 ── */
.confirm-card {
border: 1px solid var(--border);
border-radius: 10px;
background: #fff;
padding: 16px 18px;
transition: box-shadow 0.15s, border-color 0.15s;
}
.confirm-card:hover {
border-color: var(--mint-border);
box-shadow: 0 2px 8px rgb(15 23 42 / 5%);
}
.confirm-card.is-pending {
border-left: 3px solid var(--warning);
}
.confirm-card.is-confirmed {
border-left: 3px solid var(--primary);
opacity: 0.92;
}
.confirm-card__head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
margin-bottom: 12px;
}
.confirm-card__name {
font-size: 15px;
font-weight: 600;
margin-bottom: 2px;
}
.confirm-card__sub {
font-size: 12px;
color: var(--muted);
}
.confirm-card__amount {
text-align: right;
flex-shrink: 0;
}
.confirm-card__amount-val {
font-size: 18px;
font-weight: 700;
color: var(--primary-dark);
font-variant-numeric: tabular-nums;
}
.confirm-card__amount-label {
font-size: 11px;
color: var(--muted);
}
.confirm-card__grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8px 16px;
margin-bottom: 14px;
}
.confirm-card__field label {
display: block;
font-size: 11px;
color: var(--muted);
margin-bottom: 2px;
}
.confirm-card__field span {
font-size: 13px;
color: var(--text);
}
.confirm-card__foot {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding-top: 12px;
border-top: 1px solid #f1f5f9;
}
.confirm-card__meta {
font-size: 12px;
color: var(--muted);
}
.btn-op {
height: 32px;
padding: 0 14px;
border-radius: 8px;
font-size: 13px;
font-weight: 500;
cursor: pointer;
border: 1px solid var(--primary);
background: var(--primary);
color: #fff;
}
.btn-op.ghost {
border-color: var(--border);
background: #fff;
color: var(--text);
}
/* ── 分区标题 ── */
.section-head {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 24px 12px;
}
.section-head h3 {
display: flex;
align-items: center;
gap: 8px;
font-size: 14px;
font-weight: 600;
}
.section-head h3::before {
content: '';
width: 4px;
height: 12px;
border-radius: 999px;
background: var(--primary-dark);
}
.section-head.is-pending h3::before {
background: var(--warning);
}
.section-count {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 22px;
height: 22px;
padding: 0 6px;
border-radius: 999px;
background: #f1f5f9;
font-size: 12px;
font-weight: 600;
color: var(--muted);
}
.section-head.is-pending .section-count {
background: var(--warning-bg);
color: var(--warning);
}
.section-toggle {
font-size: 12px;
color: var(--primary-dark);
background: none;
border: none;
cursor: pointer;
}
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
gap: 12px;
padding: 0 24px 20px;
}
.section-divider {
height: 8px;
background: #f8fafc;
border-top: 1px solid var(--border);
border-bottom: 1px solid var(--border);
}
/* ============================================================
方案 A:胶囊 + 上下分区卡片(用户提议)
============================================================ */
.scheme-a .panel-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
padding: 16px 24px;
border-bottom: 1px solid var(--border);
flex-wrap: wrap;
}
.scheme-a .panel-header__left {
display: flex;
align-items: center;
gap: 20px;
flex-wrap: wrap;
}
/* ============================================================
方案 B:双栏看板(左待确认 / 右已确认)
============================================================ */
.scheme-b .panel-header {
display: flex;
align-items: center;
justify-content: center;
padding: 16px 24px;
border-bottom: 1px solid var(--border);
}
.kanban {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0;
min-height: 420px;
}
.kanban-col {
padding: 16px 20px 24px;
min-width: 0;
}
.kanban-col:first-child {
border-right: 1px solid var(--border);
background: linear-gradient(180deg, #fffbeb 0%, #fff 120px);
}
.kanban-col:last-child {
background: linear-gradient(180deg, #ecfdf5 0%, #fff 120px);
}
.kanban-col__head {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 14px;
}
.kanban-col__head h3 {
font-size: 13px;
font-weight: 600;
display: flex;
align-items: center;
gap: 8px;
}
.kanban-stack {
display: flex;
flex-direction: column;
gap: 10px;
}
.kanban-stack .confirm-card {
border-radius: 8px;
}
.kanban-more {
margin-top: 10px;
text-align: center;
font-size: 12px;
color: var(--muted);
padding: 8px;
border: 1px dashed var(--border);
border-radius: 8px;
cursor: pointer;
}
/* ============================================================
方案 C:统计摘要 + 状态 Chip 筛选 + 卡片流
============================================================ */
.scheme-c .panel-header {
padding: 16px 24px;
border-bottom: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 12px;
}
.stat-row {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px;
padding: 16px 24px;
border-bottom: 1px solid var(--border);
}
.stat-card {
padding: 14px 16px;
border: 1px solid var(--border);
border-radius: 10px;
background: #fafbfc;
}
.stat-card__label {
font-size: 12px;
color: var(--muted);
margin-bottom: 4px;
}
.stat-card__val {
font-size: 22px;
font-weight: 700;
font-variant-numeric: tabular-nums;
}
.stat-card__val.warning {
color: var(--warning);
}
.stat-card__val.primary {
color: var(--primary-dark);
}
.chip-filter {
display: flex;
align-items: center;
gap: 8px;
padding: 12px 24px;
border-bottom: 1px solid var(--border);
}
.chip {
padding: 6px 14px;
border-radius: 999px;
border: 1px solid var(--border);
background: #fff;
font-size: 13px;
color: var(--muted);
cursor: pointer;
}
.chip.is-active {
border-color: var(--primary);
background: var(--primary-bg);
color: var(--primary-dark);
font-weight: 600;
}
/* ============================================================
方案 D:折叠分区(待确认默认展开,已确认折叠)
============================================================ */
.accordion-section {
border-bottom: 1px solid var(--border);
}
.accordion-section:last-child {
border-bottom: none;
}
.accordion-trigger {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
padding: 14px 24px;
border: none;
background: #fafbfc;
cursor: pointer;
text-align: left;
}
.accordion-trigger h3 {
display: flex;
align-items: center;
gap: 8px;
font-size: 14px;
font-weight: 600;
}
.accordion-trigger .chevron {
font-size: 12px;
color: var(--muted);
transition: transform 0.2s;
}
.accordion-section.is-open .accordion-trigger .chevron {
transform: rotate(180deg);
}
.accordion-body {
display: none;
padding-bottom: 4px;
}
.accordion-section.is-open .accordion-body {
display: block;
}
.scheme-d .panel-header {
display: flex;
align-items: center;
justify-content: center;
padding: 16px 24px;
border-bottom: 1px solid var(--border);
}
/* ============================================================
方案 E:混合 — 待确认卡片 + 已确认紧凑表格
============================================================ */
.scheme-e .panel-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 24px;
border-bottom: 1px solid var(--border);
flex-wrap: wrap;
gap: 12px;
}
.compact-table-wrap {
padding: 0 24px 20px;
overflow-x: auto;
}
.compact-table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
}
.compact-table th,
.compact-table td {
padding: 10px 12px;
text-align: center;
border-bottom: 1px solid #f1f5f9;
white-space: nowrap;
}
.compact-table th {
font-size: 12px;
font-weight: 500;
color: var(--muted);
background: #fafbfc;
}
.compact-table tbody tr:hover {
background: #f8fafc;
}
.empty-hint {
padding: 32px 24px;
text-align: center;
color: var(--muted);
font-size: 13px;
}
@media (max-width: 900px) {
.filter-grid {
grid-template-columns: 1fr;
}
.kanban {
grid-template-columns: 1fr;
}
.kanban-col:first-child {
border-right: none;
border-bottom: 1px solid var(--border);
}
.stat-row {
grid-template-columns: repeat(2, 1fr);
}
.confirm-card__grid {
grid-template-columns: 1fr 1fr;
}
}
</style>
</head>
<body>
<div class="page-head">
<h1>缴退费财务确认 · 布局方案 Demo</h1>
<p>
当前页面存在<strong>两层 Tab</strong>(缴费/退费 大卡片切换 + 待确认/已确认 胶囊 Tab),顶部视觉层级过多。
以下 5 种方案均尝试<strong>合并或消除第二层 Tab</strong>,并将列表改为卡片或混合展示。
色值与胶囊样式对齐 Fresh Mint 规范(<code>--primary #10b981</code>)。
</p>
</div>
<nav class="scheme-nav">
<a href="#scheme-a">A · 上下分区卡片</a>
<a href="#scheme-b">B · 双栏看板</a>
<a href="#scheme-c">C · 统计 + Chip 筛选</a>
<a href="#scheme-d">D · 折叠分区</a>
<a href="#scheme-e">E · 混合(卡片+表格)</a>
</nav>
<!-- ═══════════════════════════════════════════════════════════
方案 A:用户提议 — 胶囊 + 上待确认 / 下已确认
═══════════════════════════════════════════════════════════ -->
<section class="demo-block scheme-a" id="scheme-a">
<div class="demo-label">
<div>
<strong>方案 A · 胶囊切换 + 上下分区卡片</strong>
<span>缴费/退费改为居中胶囊;取消「待确认/已确认」Tab,改为同屏上下两个区域。待确认优先展示、视觉强调;已确认区域可折叠。适合财务「先处理队列、再查历史」的工作流。</span>
</div>
<span class="tag-rec">推荐</span>
</div>
<div class="panel-shell">
<div class="panel-header">
<div class="panel-header__left">
<h2 class="title-bar-heading">缴退费财务确认</h2>
<div class="type-capsule" role="tablist">
<button type="button" class="type-capsule__btn is-active" role="tab">
缴费确认
<span class="type-capsule__badge">3</span>
</button>
<button type="button" class="type-capsule__btn" role="tab">
退费确认
<span class="type-capsule__badge">1</span>
</button>
</div>
</div>
</div>
<div class="filter-block">
<div class="filter-grid">
<div class="filter-field">
<label>关键词</label>
<input type="text" placeholder="客户姓名/身份证号/新生儿姓名/新生儿身份证号" />
</div>
<div class="filter-field">
<label>应缴费时间</label>
<div class="fake-date">2026-05-30 至 2026-06-29</div>
</div>
</div>
<div class="filter-actions-row">
<span class="filter-hint">默认展示应缴费时间前后 15 天内的明细</span>
<div class="filter-actions-end">
<button type="button" class="btn">重置</button>
<button type="button" class="btn btn-main">搜索</button>
</div>
</div>
</div>
<div class="section-head is-pending">
<h3>待确认 <span class="section-count">3</span></h3>
</div>
<div class="card-grid" id="cards-pending-a"></div>
<div class="section-divider"></div>
<div class="section-head">
<h3>已确认 <span class="section-count">12</span></h3>
<button type="button" class="section-toggle">收起 ▲</button>
</div>
<div class="card-grid" id="cards-confirmed-a"></div>
</div>
</section>
<!-- ═══════════════════════════════════════════════════════════
方案 B:双栏看板
═══════════════════════════════════════════════════════════ -->
<section class="demo-block scheme-b" id="scheme-b">
<div class="demo-label">
<div>
<strong>方案 B · 双栏看板(左待确认 / 右已确认)</strong>
<span>一屏对比两个队列,适合宽屏。左侧琥珀色调强调待办,右侧绿色调表示已完成。每列独立滚动,底部「加载更多」。</span>
</div>
</div>
<div class="panel-shell">
<div class="panel-header">
<div class="type-capsule">
<button type="button" class="type-capsule__btn is-active">缴费确认 <span class="type-capsule__badge">3</span></button>
<button type="button" class="type-capsule__btn">退费确认 <span class="type-capsule__badge">1</span></button>
</div>
</div>
<div class="filter-block" style="padding: 12px 24px">
<div class="filter-grid" style="grid-template-columns: 1fr 240px auto; align-items: end">
<div class="filter-field">
<label>关键词</label>
<input type="text" placeholder="客户姓名/身份证号…" />
</div>
<div class="filter-field">
<label>应缴费时间</label>
<div class="fake-date">2026-05-30 至 2026-06-29</div>
</div>
<div class="filter-actions-end" style="margin-top: 0">
<button type="button" class="btn btn-main">搜索</button>
</div>
</div>
</div>
<div class="kanban">
<div class="kanban-col">
<div class="kanban-col__head">
<h3><span class="tag warning">待确认</span> 3 条</h3>
</div>
<div class="kanban-stack" id="cards-pending-b"></div>
<div class="kanban-more">加载更多待确认…</div>
</div>
<div class="kanban-col">
<div class="kanban-col__head">
<h3><span class="tag success">已确认</span> 12 条</h3>
</div>
<div class="kanban-stack" id="cards-confirmed-b"></div>
<div class="kanban-more">加载更多已确认…</div>
</div>
</div>
</div>
</section>
<!-- ═══════════════════════════════════════════════════════════
方案 C:统计摘要 + Chip 筛选
═══════════════════════════════════════════════════════════ -->
<section class="demo-block scheme-c" id="scheme-c">
<div class="demo-label">
<div>
<strong>方案 C · 统计摘要 + 状态 Chip 筛选 + 卡片流</strong>
<span>顶部 4 个统计卡提供概览;第二层 Tab 改为轻量 Chip(全部/待确认/已确认),减少视觉重量。单区域卡片网格,切换 Chip 时过滤。</span>
</div>
</div>
<div class="panel-shell">
<div class="panel-header">
<h2 class="title-bar-heading">缴退费财务确认</h2>
<div class="type-capsule">
<button type="button" class="type-capsule__btn is-active">缴费确认</button>
<button type="button" class="type-capsule__btn">退费确认</button>
</div>
</div>
<div class="stat-row">
<div class="stat-card">
<div class="stat-card__label">待确认</div>
<div class="stat-card__val warning">3</div>
</div>
<div class="stat-card">
<div class="stat-card__label">今日已确认</div>
<div class="stat-card__val primary">5</div>
</div>
<div class="stat-card">
<div class="stat-card__label">待确认金额</div>
<div class="stat-card__val warning">¥28,600</div>
</div>
<div class="stat-card">
<div class="stat-card__label">本月已确认</div>
<div class="stat-card__val primary">¥186,400</div>
</div>
</div>
<div class="chip-filter" role="tablist">
<button type="button" class="chip is-active" data-filter="all">全部 15</button>
<button type="button" class="chip" data-filter="pending">待确认 3</button>
<button type="button" class="chip" data-filter="confirmed">已确认 12</button>
</div>
<div class="filter-block" style="padding-top: 12px">
<div class="filter-grid">
<div class="filter-field">
<label>关键词</label>
<input type="text" placeholder="客户姓名/身份证号…" />
</div>
<div class="filter-field">
<label>应缴费时间</label>
<div class="fake-date">2026-05-30 至 2026-06-29</div>
</div>
</div>
</div>
<div class="card-grid" id="cards-c" style="padding-top: 8px"></div>
</div>
</section>
<!-- ═══════════════════════════════════════════════════════════
方案 D:折叠分区
═══════════════════════════════════════════════════════════ -->
<section class="demo-block scheme-d" id="scheme-d">
<div class="demo-label">
<div>
<strong>方案 D · 折叠手风琴分区</strong>
<span>待确认默认展开(财务主任务),已确认默认折叠节省纵向空间。比方案 A 更紧凑,适合待确认量不大、已确认历史很多的场景。</span>
</div>
</div>
<div class="panel-shell">
<div class="panel-header">
<div class="type-capsule">
<button type="button" class="type-capsule__btn is-active">缴费确认</button>
<button type="button" class="type-capsule__btn">退费确认</button>
</div>
</div>
<div class="filter-block">
<div class="filter-grid">
<div class="filter-field">
<label>关键词</label>
<input type="text" placeholder="客户姓名/身份证号…" />
</div>
<div class="filter-field">
<label>应缴费时间</label>
<div class="fake-date">2026-05-30 至 2026-06-29</div>
</div>
</div>
</div>
<div class="accordion-section is-open" data-accordion>
<button type="button" class="accordion-trigger">
<h3><span class="tag warning">待确认</span> <span class="section-count">3</span></h3>
<span class="chevron">▼</span>
</button>
<div class="accordion-body">
<div class="card-grid" id="cards-pending-d"></div>
</div>
</div>
<div class="accordion-section" data-accordion>
<button type="button" class="accordion-trigger">
<h3><span class="tag success">已确认</span> <span class="section-count">12</span></h3>
<span class="chevron">▼</span>
</button>
<div class="accordion-body">
<div class="card-grid" id="cards-confirmed-d"></div>
</div>
</div>
</div>
</section>
<!-- ═══════════════════════════════════════════════════════════
方案 E:混合 — 待确认卡片 + 已确认表格
═══════════════════════════════════════════════════════════ -->
<section class="demo-block scheme-e" id="scheme-e">
<div class="demo-label">
<div>
<strong>方案 E · 混合布局(待确认卡片 + 已确认紧凑表格)</strong>
<span>待办用卡片突出操作;已确认历史量大、字段多,保留表格 + 分页更高效。折中方案,改动风险最低。</span>
</div>
</div>
<div class="panel-shell">
<div class="panel-header">
<h2 class="title-bar-heading">缴退费财务确认</h2>
<div class="type-capsule">
<button type="button" class="type-capsule__btn is-active">缴费确认</button>
<button type="button" class="type-capsule__btn">退费确认</button>
</div>
</div>
<div class="filter-block">
<div class="filter-grid">
<div class="filter-field">
<label>关键词</label>
<input type="text" placeholder="客户姓名/身份证号…" />
</div>
<div class="filter-field">
<label>应缴费时间</label>
<div class="fake-date">2026-05-30 至 2026-06-29</div>
</div>
</div>
</div>
<div class="section-head is-pending">
<h3>待确认 <span class="section-count">3</span></h3>
</div>
<div class="card-grid" id="cards-pending-e"></div>
<div class="section-divider"></div>
<div class="section-head">
<h3>已确认 <span class="section-count">12</span></h3>
</div>
<div class="compact-table-wrap">
<table class="compact-table">
<thead>
<tr>
<th>客户姓名</th>
<th>期数</th>
<th>应缴金额</th>
<th>实缴金额</th>
<th>转账时间</th>
<th>确认时间</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody id="table-confirmed-e"></tbody>
</table>
</div>
</div>
</section>
<script>
const MOCK_PENDING = [
{
motherName: '张丽华',
motherIdCard: '340***********1234',
newbornName: '张小宝',
installmentNo: 2,
installmentDueDate: '2026-06-18',
dueAmount: '¥12,800.00',
transferAmount: '¥12,800.00',
payMode: '分期',
transferType: '银行转账',
transferTime: '2026-06-14 10:32',
protocolStatus: '进行中',
createTime: '2026-06-14 09:15'
},
{
motherName: '王美玲',
motherIdCard: '340***********5678',
newbornName: '王乐乐',
installmentNo: 1,
installmentDueDate: '2026-06-20',
dueAmount: '¥8,600.00',
transferAmount: '¥8,600.00',
payMode: '一次性',
transferType: '微信',
transferTime: '2026-06-13 16:48',
protocolStatus: '进行中',
createTime: '2026-06-13 17:02'
},
{
motherName: '陈晓燕',
motherIdCard: '340***********9012',
newbornName: '—',
installmentNo: 3,
installmentDueDate: '2026-06-22',
dueAmount: '¥7,200.00',
transferAmount: '¥7,200.00',
payMode: '分期',
transferType: '支付宝',
transferTime: '2026-06-12 11:20',
protocolStatus: '进行中',
createTime: '2026-06-12 11:25'
}
]
const MOCK_CONFIRMED = [
{
motherName: '李婷婷',
installmentNo: 1,
dueAmount: '¥15,000.00',
transferAmount: '¥15,000.00',
transferTime: '2026-06-10 14:22',
updateTime: '2026-06-10 15:01',
financeRemark: '凭证齐全'
},
{
motherName: '赵敏',
installmentNo: 2,
dueAmount: '¥9,800.00',
transferAmount: '¥9,800.00',
transferTime: '2026-06-08 09:15',
updateTime: '2026-06-08 10:30',
financeRemark: '—'
}
]
function renderCard(item, mode) {
const isPending = mode === 'pending'
const compact = mode === 'compact'
return `
<article class="confirm-card ${isPending ? 'is-pending' : 'is-confirmed'}">
<div class="confirm-card__head">
<div>
<div class="confirm-card__name">${item.motherName}</div>
<div class="confirm-card__sub">${item.motherIdCard || ''}${item.newbornName ? ' · 新生儿 ' + item.newbornName : ''}</div>
</div>
<div class="confirm-card__amount">
<div class="confirm-card__amount-val">${item.transferAmount || item.dueAmount}</div>
<div class="confirm-card__amount-label">${isPending ? '实缴金额' : '已确认'}</div>
</div>
</div>
${
compact
? ''
: `<div class="confirm-card__grid">
<div class="confirm-card__field"><label>期数</label><span>第 ${item.installmentNo} 期</span></div>
<div class="confirm-card__field"><label>应缴时间</label><span>${item.installmentDueDate}</span></div>
<div class="confirm-card__field"><label>应缴金额</label><span>${item.dueAmount}</span></div>
<div class="confirm-card__field"><label>缴费方式</label><span>${item.payMode || '—'}</span></div>
<div class="confirm-card__field"><label>转账方式</label><span>${item.transferType || '—'}</span></div>
<div class="confirm-card__field"><label>转账时间</label><span>${item.transferTime || '—'}</span></div>
</div>`
}
<div class="confirm-card__foot">
<div class="confirm-card__meta">
${isPending ? `<span class="tag warning">缴费确认中</span> · 提交 ${item.createTime}` : `<span class="tag success">已缴费</span> · 确认 ${item.updateTime}`}
</div>
<button type="button" class="btn-op ${isPending ? '' : 'ghost'}">${isPending ? '确认收款' : '查看确认信息'}</button>
</div>
</article>
`
}
function fillCards(containerId, items, mode, limit) {
const el = document.getElementById(containerId)
if (!el) return
el.innerHTML = items.slice(0, limit ?? items.length).map((i) => renderCard(i, mode)).join('')
}
// 方案 A
fillCards('cards-pending-a', MOCK_PENDING, 'pending')
fillCards('cards-confirmed-a', MOCK_CONFIRMED, 'confirmed')
// 方案 B
fillCards('cards-pending-b', MOCK_PENDING, 'pending')
fillCards('cards-confirmed-b', MOCK_CONFIRMED, 'confirmed')
// 方案 C — 全部卡片 + Chip 筛选
const allItems = [
...MOCK_PENDING.map((i) => ({ ...i, _status: 'pending' })),
...MOCK_CONFIRMED.map((i) => ({ ...i, _status: 'confirmed' }))
]
const cardsC = document.getElementById('cards-c')
function renderC(filter) {
const list =
filter === 'all'
? allItems
: allItems.filter((i) => i._status === filter)
cardsC.innerHTML = list
.map((i) => renderCard(i, i._status === 'pending' ? 'pending' : 'confirmed'))
.join('')
}
renderC('all')
document.querySelectorAll('.chip-filter .chip').forEach((chip) => {
chip.addEventListener('click', () => {
document.querySelectorAll('.chip-filter .chip').forEach((c) => c.classList.remove('is-active'))
chip.classList.add('is-active')
renderC(chip.dataset.filter)
})
})
// 方案 D
fillCards('cards-pending-d', MOCK_PENDING, 'pending')
fillCards('cards-confirmed-d', MOCK_CONFIRMED, 'confirmed')
document.querySelectorAll('[data-accordion]').forEach((section) => {
section.querySelector('.accordion-trigger').addEventListener('click', () => {
section.classList.toggle('is-open')
})
})
// 方案 E
fillCards('cards-pending-e', MOCK_PENDING, 'pending')
document.getElementById('table-confirmed-e').innerHTML = MOCK_CONFIRMED.map(
(row) => `
<tr>
<td>${row.motherName}</td>
<td>第 ${row.installmentNo} 期</td>
<td>${row.dueAmount}</td>
<td>${row.transferAmount}</td>
<td>${row.transferTime}</td>
<td>${row.updateTime}</td>
<td><span class="tag success">已缴费</span></td>
<td><button type="button" class="btn-op ghost" style="height:28px;padding:0 10px;font-size:12px">查看</button></td>
</tr>
`
).join('')
// 胶囊切换交互(视觉演示)
document.querySelectorAll('.type-capsule').forEach((group) => {
group.querySelectorAll('.type-capsule__btn').forEach((btn) => {
btn.addEventListener('click', () => {
group.querySelectorAll('.type-capsule__btn').forEach((b) => b.classList.remove('is-active'))
btn.classList.add('is-active')
})
})
})
</script>
</body>
</html>