Files
zkxw/docs/demos/2026-10-14-payment-card-period-collapse-demo.html
T
zlwuandCursor 42dde4b0bc docs: design payment list card period collapse for mobile market H5
Spec and interactive demo for collapsing payment installments on list cards (summary row + expand details).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-14 14:24:12 +08:00

565 lines
18 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>缴费信息 · 列表卡片期数折叠 Demo</title>
<style>
:root {
--primary: #0a9f6d;
--primary-dark: #087f57;
--primary-soft: #e9f9f2;
--text: #18332a;
--muted: #6b7c74;
--border: #dce8e2;
--surface: #fff;
--page: #f3f6f5;
--money: #c98312;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", sans-serif;
font-size: 14px;
line-height: 1.5;
color: var(--text);
background: var(--page);
}
.page {
max-width: 420px;
margin: 0 auto;
padding: 20px 14px 48px;
}
.hero { margin-bottom: 18px; }
.hero h1 {
margin: 0 0 6px;
font-size: 20px;
font-weight: 700;
}
.hero p {
margin: 0;
color: var(--muted);
font-size: 13px;
}
.section-label {
display: flex;
align-items: center;
justify-content: space-between;
margin: 18px 0 8px;
color: var(--muted);
font-size: 12px;
font-weight: 600;
}
.section-label em {
font-style: normal;
color: var(--primary-dark);
background: var(--primary-soft);
padding: 2px 8px;
border-radius: 999px;
}
.section-label .bad {
color: #b45309;
background: #fff7e8;
}
.card {
padding: 14px;
border: 1px solid var(--border);
border-radius: 16px;
background: var(--surface);
box-shadow: 0 6px 20px rgb(8 127 87 / 7%);
}
.card + .card { margin-top: 12px; }
.head {
display: flex;
align-items: center;
gap: 10px;
padding-bottom: 12px;
border-bottom: 1px solid #eef4f1;
}
.index {
display: grid;
width: 30px;
height: 30px;
flex: 0 0 30px;
place-items: center;
border-radius: 50%;
background: var(--primary-soft);
color: var(--primary-dark);
font-size: 13px;
font-weight: 700;
}
.identity {
min-width: 0;
flex: 1;
display: flex;
flex-direction: column;
gap: 3px;
}
.title {
overflow: hidden;
font-size: 16px;
font-weight: 700;
text-overflow: ellipsis;
white-space: nowrap;
}
.subtitle {
overflow: hidden;
color: var(--muted);
font-size: 12px;
text-overflow: ellipsis;
white-space: nowrap;
}
.tag {
display: inline-flex;
max-width: 128px;
align-self: center;
padding: 5px 12px;
overflow: hidden;
border-radius: 999px;
background: #fff7e8;
color: #b45309;
font-size: 12px;
line-height: 1.3;
text-overflow: ellipsis;
white-space: nowrap;
}
.tag.ok {
background: var(--primary-soft);
color: var(--primary-dark);
}
.tag.mode {
background: #eef2ff;
color: #4338ca;
}
.fields {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px 16px;
padding: 14px 0;
}
.field {
display: flex;
min-width: 0;
flex-direction: column;
gap: 4px;
color: var(--muted);
font-size: 12px;
}
.field.wide { grid-column: 1 / -1; }
.field b {
color: var(--text);
font-weight: 500;
overflow-wrap: anywhere;
}
.field b.money {
color: var(--money);
font-size: 15px;
font-weight: 700;
}
/* —— 期数折叠区 —— */
.periods {
margin: 0 0 12px;
border: 1px solid #eef4f1;
border-radius: 12px;
background: #fafcfb;
overflow: hidden;
}
.period {
border-top: 1px solid #eef4f1;
}
.period:first-child { border-top: 0; }
.period__toggle {
display: grid;
width: 100%;
min-height: 48px;
grid-template-columns: 64px 1fr 1fr 20px;
align-items: center;
gap: 8px;
padding: 10px 12px;
border: 0;
background: transparent;
color: var(--text);
font: inherit;
text-align: left;
cursor: pointer;
}
.period__toggle:active { background: #f0f7f3; }
.period__no {
font-size: 13px;
font-weight: 700;
color: var(--primary-dark);
}
.period__col {
min-width: 0;
display: flex;
flex-direction: column;
gap: 2px;
}
.period__col span {
color: var(--muted);
font-size: 11px;
}
.period__col b {
color: var(--money);
font-size: 13px;
font-weight: 700;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.period__chevron {
color: var(--muted);
font-size: 12px;
text-align: center;
transition: transform 0.2s ease;
}
.period.is-open .period__chevron {
transform: rotate(180deg);
}
.period__body {
display: none;
padding: 0 12px 12px;
border-top: 1px dashed #eef4f1;
}
.period.is-open .period__body { display: block; }
.period__body .fields {
padding: 10px 0 0;
gap: 10px 12px;
}
.actions {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
gap: 8px;
padding-top: 12px;
border-top: 1px solid #eef4f1;
}
.btn {
min-width: 76px;
min-height: 44px;
padding: 0 14px;
border-radius: 9px;
border: 1px solid var(--border);
background: #fff;
color: var(--text);
font-size: 13px;
cursor: pointer;
}
.btn.primary {
border-color: var(--primary);
background: var(--primary);
color: #fff;
}
.hint {
margin-top: 16px;
padding: 12px 14px;
border-radius: 12px;
background: #fff;
border: 1px dashed var(--border);
color: var(--muted);
font-size: 12px;
}
.hint strong { color: var(--text); }
.hint code {
display: inline-block;
margin-top: 4px;
font-size: 11px;
word-break: break-all;
}
.before-note {
margin: 0 0 10px;
color: #b45309;
font-size: 12px;
}
</style>
</head>
<body>
<div class="page">
<header class="hero">
<h1>缴费信息 · 期数折叠</h1>
<p>列表卡片按期折叠:默认只显示「第几期 / 应缴 / 已缴」,点击展开明细。</p>
</header>
<!-- ========== 改后(推荐) ========== -->
<div class="section-label">
<span>改后(默认折叠)</span>
<em>推荐</em>
</div>
<article class="card">
<header class="head">
<span class="index">1</span>
<span class="identity">
<strong class="title">周雨桐</strong>
<small class="subtitle">S-10021</small>
</span>
<span class="tag">部分已缴</span>
</header>
<div class="fields">
<div class="field wide"><span>协议号</span><b>XY20261008012</b></div>
<div class="field"><span>姓名</span><b>周雨桐</b></div>
<div class="field"><span>手机号</span><b>138****6621</b></div>
<div class="field wide"><span>样本编码</span><b>S-10021</b></div>
<div class="field"><span>签署日期</span><b>2026-10-01</b></div>
<div class="field"><span>存储年限</span><b>20</b></div>
<div class="field wide"><span>存储项目</span><b>脐带血</b></div>
<div class="field"><span>合同总额</span><b class="money">¥10,000.00</b></div>
<div class="field"><span>缴费方式</span><span class="tag mode">分期</span></div>
<div class="field"><span>优惠金额</span><b class="money">¥1,000.00</b></div>
<div class="field"><span>应收总额</span><b class="money">¥9,000.00</b></div>
</div>
<div class="periods" data-periods>
<!-- 第1期 -->
<div class="period" data-period>
<button type="button" class="period__toggle" aria-expanded="false">
<span class="period__no">第1期</span>
<span class="period__col">
<span>应缴费金额</span>
<b>¥3,000.00</b>
</span>
<span class="period__col">
<span>已缴费金额</span>
<b>¥3,000.00</b>
</span>
<span class="period__chevron">▾</span>
</button>
<div class="period__body">
<div class="fields">
<div class="field"><span>应缴费时间</span><b>2026-10-10</b></div>
<div class="field"><span>已缴费时间</span><b>2026-10-11</b></div>
<div class="field wide"><span>欠缴费金额</span><b class="money">¥0.00</b></div>
</div>
</div>
</div>
<!-- 第2期 -->
<div class="period" data-period>
<button type="button" class="period__toggle" aria-expanded="false">
<span class="period__no">第2期</span>
<span class="period__col">
<span>应缴费金额</span>
<b>¥2,000.00</b>
</span>
<span class="period__col">
<span>已缴费金额</span>
<b>¥0.00</b>
</span>
<span class="period__chevron">▾</span>
</button>
<div class="period__body">
<div class="fields">
<div class="field"><span>应缴费时间</span><b>2027-04-10</b></div>
<div class="field"><span>已缴费时间</span><b>—</b></div>
<div class="field wide"><span>欠缴费金额</span><b class="money">¥2,000.00</b></div>
</div>
</div>
</div>
<!-- 第3期 -->
<div class="period" data-period>
<button type="button" class="period__toggle" aria-expanded="false">
<span class="period__no">第3期</span>
<span class="period__col">
<span>应缴费金额</span>
<b>¥2,000.00</b>
</span>
<span class="period__col">
<span>已缴费金额</span>
<b>¥0.00</b>
</span>
<span class="period__chevron">▾</span>
</button>
<div class="period__body">
<div class="fields">
<div class="field"><span>应缴费时间</span><b>2027-10-10</b></div>
<div class="field"><span>已缴费时间</span><b>—</b></div>
<div class="field wide"><span>欠缴费金额</span><b class="money">¥2,000.00</b></div>
</div>
</div>
</div>
<!-- 第4期 -->
<div class="period" data-period>
<button type="button" class="period__toggle" aria-expanded="false">
<span class="period__no">第4期</span>
<span class="period__col">
<span>应缴费金额</span>
<b>¥2,000.00</b>
</span>
<span class="period__col">
<span>已缴费金额</span>
<b>¥0.00</b>
</span>
<span class="period__chevron">▾</span>
</button>
<div class="period__body">
<div class="fields">
<div class="field"><span>应缴费时间</span><b>2028-04-10</b></div>
<div class="field"><span>已缴费时间</span><b>—</b></div>
<div class="field wide"><span>欠缴费金额</span><b class="money">¥2,000.00</b></div>
</div>
</div>
</div>
</div>
<div class="fields" style="padding-top: 0;">
<div class="field"><span>累计实缴</span><b class="money">¥3,000.00</b></div>
<div class="field"><span>待缴金额</span><b class="money">¥6,000.00</b></div>
<div class="field wide"><span>备注</span><b>首期已缴</b></div>
</div>
<footer class="actions">
<button type="button" class="btn">查看协议</button>
<button type="button" class="btn primary">缴费明细</button>
</footer>
</article>
<!-- ========== 展开态示意 ========== -->
<div class="section-label">
<span>展开态示意(第1、2期已展开)</span>
<em>可点击切换</em>
</div>
<article class="card">
<header class="head">
<span class="index">2</span>
<span class="identity">
<strong class="title">李婷</strong>
<small class="subtitle">S-10022</small>
</span>
<span class="tag ok">已缴清</span>
</header>
<div class="fields">
<div class="field wide"><span>协议号</span><b>XY20261008018</b></div>
<div class="field"><span>合同总额</span><b class="money">¥6,000.00</b></div>
<div class="field"><span>缴费方式</span><span class="tag mode">分期</span></div>
</div>
<div class="periods" data-periods>
<div class="period is-open" data-period>
<button type="button" class="period__toggle" aria-expanded="true">
<span class="period__no">第1期</span>
<span class="period__col">
<span>应缴费金额</span>
<b>¥3,000.00</b>
</span>
<span class="period__col">
<span>已缴费金额</span>
<b>¥3,000.00</b>
</span>
<span class="period__chevron">▾</span>
</button>
<div class="period__body">
<div class="fields">
<div class="field"><span>应缴费时间</span><b>2026-09-01</b></div>
<div class="field"><span>已缴费时间</span><b>2026-09-02</b></div>
<div class="field wide"><span>欠缴费金额</span><b class="money">¥0.00</b></div>
</div>
</div>
</div>
<div class="period is-open" data-period>
<button type="button" class="period__toggle" aria-expanded="true">
<span class="period__no">第2期</span>
<span class="period__col">
<span>应缴费金额</span>
<b>¥3,000.00</b>
</span>
<span class="period__col">
<span>已缴费金额</span>
<b>¥3,000.00</b>
</span>
<span class="period__chevron">▾</span>
</button>
<div class="period__body">
<div class="fields">
<div class="field"><span>应缴费时间</span><b>2027-03-01</b></div>
<div class="field"><span>已缴费时间</span><b>2027-03-01</b></div>
<div class="field wide"><span>欠缴费金额</span><b class="money">¥0.00</b></div>
</div>
</div>
</div>
</div>
<footer class="actions">
<button type="button" class="btn">查看协议</button>
<button type="button" class="btn primary">缴费明细</button>
</footer>
</article>
<!-- ========== 改前对比 ========== -->
<div class="section-label">
<span>改前(全部平铺)</span>
<em class="bad">卡片过高</em>
</div>
<p class="before-note">当前实现:固定 6 期 × 5 个字段 = 约 30 行期次字段,列表扫读困难。</p>
<article class="card">
<header class="head">
<span class="index">3</span>
<span class="identity">
<strong class="title">周雨桐</strong>
<small class="subtitle">S-10021</small>
</span>
<span class="tag">部分已缴</span>
</header>
<div class="fields">
<div class="field wide"><span>协议号</span><b>XY20261008012</b></div>
<div class="field"><span>合同总额</span><b class="money">¥10,000.00</b></div>
<div class="field"><span>缴费方式</span><span class="tag mode">分期</span></div>
<div class="field"><span>第1期·应缴费金额(元)</span><b class="money">¥3,000.00</b></div>
<div class="field"><span>第1期·应缴费时间</span><b>2026-10-10</b></div>
<div class="field"><span>第1期·已缴费金额</span><b class="money">¥3,000.00</b></div>
<div class="field"><span>第1期·已缴费时间</span><b>2026-10-11</b></div>
<div class="field wide"><span>第1期·欠缴费金额</span><b class="money">¥0.00</b></div>
<div class="field"><span>第2期·应缴费金额(元)</span><b class="money">¥2,000.00</b></div>
<div class="field"><span>第2期·应缴费时间</span><b>2027-04-10</b></div>
<div class="field"><span>第2期·已缴费金额</span><b class="money">¥0.00</b></div>
<div class="field"><span>第2期·已缴费时间</span><b>—</b></div>
<div class="field wide"><span>第2期·欠缴费金额</span><b class="money">¥2,000.00</b></div>
<div class="field wide"><span>…第3~6期同样平铺…</span><b>卡片继续变高</b></div>
<div class="field"><span>累计实缴</span><b class="money">¥3,000.00</b></div>
<div class="field"><span>待缴金额</span><b class="money">¥6,000.00</b></div>
</div>
<footer class="actions">
<button type="button" class="btn">查看协议</button>
<button type="button" class="btn primary">缴费明细</button>
</footer>
</article>
<div class="hint">
<strong>交互说明:</strong>只渲染有数据的期次;每期独立一行摘要(第N期 · 应缴 · 已缴),默认折叠;点击展开应缴时间 / 已缴时间 / 欠缴金额;多期可同时展开。
<br />
<code>docs/demos/2026-10-14-payment-card-period-collapse-demo.html</code>
</div>
</div>
<script>
document.querySelectorAll('[data-period]').forEach((row) => {
const btn = row.querySelector('.period__toggle')
btn.addEventListener('click', () => {
const open = row.classList.toggle('is-open')
btn.setAttribute('aria-expanded', open ? 'true' : 'false')
})
})
</script>
</body>
</html>