feat: 安装费汇总与店铺明细改为横向页签 (#634)

This commit is contained in:
qiuxiang 2026-10-26 19:27:38 +08:00
parent d9b5d80c60
commit 88ec7d01f2
2 changed files with 140 additions and 26 deletions

View File

@ -291,6 +291,47 @@
border-bottom: 1px solid #eee8dd;
}
.installation-fee-tabs {
display: flex;
align-items: stretch;
gap: 1.25rem;
overflow-x: auto;
padding: 0 1.1rem;
border-bottom: 1px solid #e8e0d2;
background: #ffffff;
overscroll-behavior-inline: contain;
scrollbar-width: thin;
white-space: nowrap;
}
.installation-fee-tab {
flex: 0 0 auto;
min-height: 2.75rem;
padding: 0 0.2rem;
border: 0;
border-bottom: 2px solid transparent;
background: transparent;
color: #595959;
cursor: pointer;
font: inherit;
font-size: 0.8125rem;
font-weight: 600;
}
.installation-fee-tab:hover {
color: #856632;
}
.installation-fee-tab[aria-selected="true"] {
border-bottom-color: #b9954f;
color: #856632;
}
.installation-fee-tab:focus-visible {
outline: 3px solid rgba(133, 102, 50, 0.2);
outline-offset: -3px;
}
.installation-fee-filter span {
display: block;
margin-bottom: 0.25rem;
@ -353,15 +394,8 @@
}
.installation-fee-platform-summary {
margin: 0.75rem 0 1rem;
padding-top: 0.75rem;
border-top: 1px solid #d8d2c7;
}
.installation-fee-platform-summary h3 {
margin: 0 0 0.5rem;
color: #171717;
font-size: 0.75rem;
margin: 0;
padding: 0;
}
.installation-fee-platform-summary table {
@ -481,9 +515,12 @@
</select>
</label>
</div>
<div class="installation-fee-tabs" role="tablist" aria-label="安装费汇总子页面">
<button type="button" class="installation-fee-tab" id="installationFeePlatformTab" role="tab" aria-selected="true" aria-controls="installationFeePlatformPanel" data-installation-fee-tab="platform" tabindex="0">平台汇总</button>
<button type="button" class="installation-fee-tab" id="installationFeeDetailTab" role="tab" aria-selected="false" aria-controls="installationFeeDetailPanel" data-installation-fee-tab="detail" tabindex="-1">店铺明细</button>
</div>
<div class="installation-fee-dialog__scroll">
<section class="installation-fee-platform-summary" aria-label="安装费平台汇总">
<h3>平台汇总</h3>
<section class="installation-fee-platform-summary" id="installationFeePlatformPanel" role="tabpanel" aria-labelledby="installationFeePlatformTab" data-installation-fee-panel="platform">
<table>
<thead>
<tr>
@ -493,22 +530,25 @@
</thead>
<tbody data-installation-fee-platform-rows></tbody>
</table>
<div class="installation-fee-empty" data-installation-fee-platform-empty hidden>当前客服审核时间内没有平台汇总。</div>
</section>
<section id="installationFeeDetailPanel" role="tabpanel" aria-labelledby="installationFeeDetailTab" data-installation-fee-panel="detail" hidden>
<table class="installation-fee-table">
<thead>
<tr>
<th scope="col">店铺名称</th>
<th scope="col">安装公司</th>
<th scope="col">收款渠道</th>
<th scope="col" class="is-number">结算明细金额</th>
</tr>
</thead>
<tbody data-installation-fee-rows></tbody>
</table>
<div class="installation-fee-empty" data-installation-fee-empty>请选择客服审核日期后查看明细</div>
</section>
<table class="installation-fee-table">
<thead>
<tr>
<th scope="col">店铺名称</th>
<th scope="col">安装公司</th>
<th scope="col">收款渠道</th>
<th scope="col" class="is-number">结算明细金额</th>
</tr>
</thead>
<tbody data-installation-fee-rows></tbody>
</table>
<div class="installation-fee-empty" data-installation-fee-empty>请选择客服审核日期后查看明细</div>
</div>
<div class="installation-fee-dialog__foot">
<span data-installation-fee-count>共 0 条明细汇总</span>
<span data-installation-fee-count>共 0 条平台汇总</span>
</div>
</dialog>
@ -538,11 +578,43 @@
var rowsEl = dialog.querySelector('[data-installation-fee-rows]');
var platformRowsEl = dialog.querySelector('[data-installation-fee-platform-rows]');
var emptyEl = dialog.querySelector('[data-installation-fee-empty]');
var platformEmptyEl = dialog.querySelector('[data-installation-fee-platform-empty]');
var countEl = dialog.querySelector('[data-installation-fee-count]');
var scrollEl = dialog.querySelector('.installation-fee-dialog__scroll');
var tabButtons = Array.from(dialog.querySelectorAll('[data-installation-fee-tab]'));
var tabPanels = Array.from(dialog.querySelectorAll('[data-installation-fee-panel]'));
var allRows = [];
var loadedSignature = '';
var timer = null;
var controller = null;
var detailRowCount = 0;
var platformRowCount = 0;
var activeTab = 'platform';
function updateCount() {
var count = activeTab === 'platform' ? platformRowCount : detailRowCount;
var suffix = activeTab === 'platform' ? '平台汇总' : '明细汇总';
countEl.textContent = '共 ' + count.toLocaleString('zh-CN') + ' 条' + suffix;
}
function activateTab(name, focusTab) {
activeTab = name;
tabButtons.forEach(function (tab) {
var selected = tab.dataset.installationFeeTab === name;
tab.setAttribute('aria-selected', selected ? 'true' : 'false');
tab.tabIndex = selected ? 0 : -1;
if (selected && focusTab) {
tab.focus();
}
});
tabPanels.forEach(function (panel) {
panel.hidden = panel.dataset.installationFeePanel !== name;
});
if (scrollEl) {
scrollEl.scrollTop = 0;
}
updateCount();
}
function yuan(value) {
return '¥' + Number(value || 0).toLocaleString('zh-CN', {
@ -709,6 +781,8 @@
byPlatform[key] ??= 0;
byPlatform[key] += Number(row.amount || 0);
});
detailRowCount = rows.length;
platformRowCount = Object.keys(byPlatform).length;
platformRowsEl.replaceChildren();
Object.keys(byPlatform).sort(function (left, right) {
return Math.abs(byPlatform[right]) - Math.abs(byPlatform[left])
@ -726,22 +800,30 @@
});
currentTotal.textContent = yuan(total);
countEl.textContent = '共 ' + rows.length.toLocaleString('zh-CN') + ' 条明细汇总';
updateCount();
emptyEl.hidden = rows.length > 0;
emptyEl.textContent = allRows.length
? '当前筛选条件下没有安装费明细。'
: '当前客服审核时间内没有安装费明细。';
platformEmptyEl.hidden = platformRowCount > 0;
platformEmptyEl.textContent = allRows.length
? '当前筛选条件下没有平台汇总。'
: '当前客服审核时间内没有平台汇总。';
}
function resetDialog(message) {
allRows = [];
loadedSignature = '';
detailRowCount = 0;
platformRowCount = 0;
rowsEl.replaceChildren();
platformRowsEl.replaceChildren();
currentTotal.textContent = '¥0.00';
countEl.textContent = '共 0 条明细汇总';
updateCount();
emptyEl.hidden = false;
emptyEl.textContent = message;
platformEmptyEl.hidden = false;
platformEmptyEl.textContent = message;
fillFilter(storeFilter, '全部店铺', []);
fillFilter(platformFilter, '全部平台', []);
fillFilter(companyFilter, '全部安装公司', []);
@ -749,6 +831,7 @@
}
function openDialog() {
activateTab('platform', false);
if (typeof dialog.showModal === 'function') {
dialog.showModal();
} else {
@ -832,6 +915,28 @@
openDialog();
refresh(false);
});
tabButtons.forEach(function (tab, index) {
tab.addEventListener('click', function () {
activateTab(tab.dataset.installationFeeTab, false);
});
tab.addEventListener('keydown', function (event) {
var nextIndex = null;
if (event.key === 'ArrowRight') {
nextIndex = (index + 1) % tabButtons.length;
} else if (event.key === 'ArrowLeft') {
nextIndex = (index - 1 + tabButtons.length) % tabButtons.length;
} else if (event.key === 'Home') {
nextIndex = 0;
} else if (event.key === 'End') {
nextIndex = tabButtons.length - 1;
}
if (nextIndex === null) {
return;
}
event.preventDefault();
activateTab(tabButtons[nextIndex].dataset.installationFeeTab, true);
});
});
[fromInput, toInput].forEach(function (input) {
if (input) { input.addEventListener('change', scheduleRefresh); }
});

View File

@ -288,6 +288,13 @@ class ManagementCrudTest extends FeatureTestCase
->assertSee('data-installation-fee-trend', false)
->assertSee('data-installation-fee-package', false)
->assertSee('data-installation-fee-non-package', false)
->assertSee('data-installation-fee-tab="platform"', false)
->assertSee('data-installation-fee-tab="detail"', false)
->assertSee('data-installation-fee-panel="platform"', false)
->assertSee('data-installation-fee-panel="detail"', false)
->assertSeeText('店铺明细')
->assertSee('overflow-x: auto', false)
->assertSeeText('共 0 条平台汇总')
->assertSee('--installation-fee-accent: #856632', false)
->assertSee('border-left: 3px solid var(--installation-fee-accent)', false)
->assertSee('border-right: 3px solid var(--installation-fee-accent)', false)
@ -303,6 +310,8 @@ class ManagementCrudTest extends FeatureTestCase
->assertSee('function captionRange(value)', false)
->assertSee('function setCardValue(total, rows, value, data)', false)
->assertSee('function wanAmount(value)', false)
->assertSee('function activateTab(name, focusTab)', false)
->assertSee("event.key === 'ArrowRight'", false)
->assertSeeText('平台')
->assertSeeText('店铺名称')
->assertSeeText('安装公司')