diff --git a/resources/views/business/pages/financial-ledger/ledger.blade.php b/resources/views/business/pages/financial-ledger/ledger.blade.php
index 408b6747..3b6fea59 100644
--- a/resources/views/business/pages/financial-ledger/ledger.blade.php
+++ b/resources/views/business/pages/financial-ledger/ledger.blade.php
@@ -302,10 +302,10 @@
.ledger-accounts-table-wrap { max-height:calc(100vh - 390px); min-height:20rem; }
#ledger-panel-accounts[aria-busy="true"] .ledger-accounts-table-wrap { opacity:.58; pointer-events:none; }
.ledger-pagination { display:flex; align-items:center; justify-content:space-between; gap:.75rem; padding:.65rem .9rem; color:var(--vip-content-muted, #595959); font-size:.72rem; }
- .ledger-pagination a { color:var(--vip-content-accent-dark, #856632); text-decoration:none; margin-left:.75rem; font-weight:600; }
+ .ledger-pagination a { color:var(--vip-content-accent-dark, #856632); text-decoration:none; font-weight:600; }
.ledger-pagination__controls { display:flex; align-items:center; justify-content:flex-end; gap:.45rem; margin-left:auto; }
- .ledger-page-box { display:inline-flex; align-items:center; gap:.1rem; height:1.7rem; }
- .ledger-page-box__arrow { display:inline-grid; place-items:center; width:1.2rem; height:1.5rem; padding:0; border:0; background:transparent; color:var(--vip-content-accent-dark, #856632); font:inherit; text-decoration:none; }
+ .ledger-page-box { display:inline-flex; align-items:center; gap:.05rem; height:1.75rem; }
+ .ledger-page-box__arrow { display:inline-grid; place-items:center; width:1.2rem; height:1.5rem; margin:0; padding:0; border:0; background:transparent; color:var(--vip-content-accent-dark, #856632); font:inherit; text-decoration:none; }
.ledger-page-box__arrow:hover { color:#6A5129; }
.ledger-page-box__arrow:focus:not(:focus-visible) { outline:none; }
.ledger-page-box__arrow:focus-visible { outline:1px solid var(--vip-content-accent-dark, #856632); outline-offset:0; border-radius:2px; }
@@ -314,6 +314,9 @@
.ledger-page-box__triangle.is-next { border-left:8px solid currentColor; }
.ledger-page-box__arrow.is-disabled { color:#b9b3a9; cursor:not-allowed; }
.ledger-page-box__current { min-width:2.2rem; padding:0 .15rem; color:var(--vip-content-ink, #171717); font-size:.7rem; font-variant-numeric:tabular-nums; font-weight:700; text-align:center; white-space:nowrap; }
+ .ledger-page-box__select { width:4.45rem; height:1.55rem; padding:0 1.25rem 0 .35rem; border:1px solid var(--vip-border, #D8D2C7); border-radius:.35rem; background:#fff; color:var(--vip-content-ink, #171717); font:inherit; font-size:.68rem; font-variant-numeric:tabular-nums; font-weight:700; text-align:center; text-align-last:center; cursor:pointer; }
+ .ledger-page-box__select:hover { border-color:var(--vip-content-accent, #B9954F); }
+ .ledger-page-box__select:focus { border-color:var(--vip-content-accent-dark, #856632); outline:none; box-shadow:0 0 0 3px rgba(133,102,50,.14); }
.ledger-empty { padding:3.5rem 1rem; text-align:center; color:var(--vip-content-muted, #595959); }
.ledger-progress { display:flex; align-items:center; gap:.65rem; min-width:15rem; }
.ledger-progress__track { flex:1; height:.45rem; overflow:hidden; border-radius:999px; background:#e8e3da; }
@@ -489,24 +492,11 @@
-
+ @include('business.pages.financial-ledger.partials.pagination', [
+ 'rows' => $ledgerAccounts,
+ 'paginationKey' => 'accounts',
+ 'paginationLabel' => '账户总表分页',
+ ])
{{-- 店铺台账 --}}
@@ -536,7 +526,11 @@
@forelse ($ledgerShops as $row)| {{ $row->shop_name }} | {{ $row->platform }} | {{ $row->company_name }} | {{ $row->account_short }} | {{ $row->status }} | {{ $row->payout_account }} | {{ $money($row->shop_balance) }} | {{ $row->remark }} |
@empty没有匹配的店铺数据。 |
@endforelse
-
+ @include('business.pages.financial-ledger.partials.pagination', [
+ 'rows' => $ledgerShops,
+ 'paginationKey' => 'shops',
+ 'paginationLabel' => '店铺台账分页',
+ ])
@@ -567,7 +561,11 @@
@forelse ($ledgerFlows as $row)| {{ $date($row->flow_date) }} | {{ $row->company_name }} | {{ $row->account_short }} | {{ $money($row->opening_balance) }} | {{ $row->inflow > 0 ? $money($row->inflow) : '' }} | {{ $row->outflow > 0 ? $money($row->outflow) : '' }} | {{ $money($row->closing_balance) }} | {{ $row->remark }} |
@empty当前筛选没有流水数据;期初日会为每个期初账户生成一行。 |
@endforelse
-
+ @include('business.pages.financial-ledger.partials.pagination', [
+ 'rows' => $ledgerFlows,
+ 'paginationKey' => 'flows',
+ 'paginationLabel' => '每日资金流水分页',
+ ])
@@ -653,7 +651,11 @@
@endforelse
-
+ @include('business.pages.financial-ledger.partials.pagination', [
+ 'rows' => $ledgerTransactions,
+ 'paginationKey' => 'transactions',
+ 'paginationLabel' => '动账明细分页',
+ ])
@@ -706,7 +708,13 @@
@forelse (($mapping['rows'] ?? collect()) as $row)| {{ $sourceLabels[$row->source] ?? $row->source }} | {{ $row->source_value }} | {{ number_format((int) $row->txn_count) }} | {{ $money($row->income_sum) }} | {{ $money($row->expense_sum) }} | @if ($canEdit)@else{{ $row->account_short ?: '未匹配' }}@endif | {{ $row->account_short ? '已映射' : '未匹配' }} |
@empty没有匹配的映射记录。 |
@endforelse
-
+ @if (($mapping['rows'] ?? null) !== null)
+ @include('business.pages.financial-ledger.partials.pagination', [
+ 'rows' => $mapping['rows'],
+ 'paginationKey' => 'mapping',
+ 'paginationLabel' => '账户映射分页',
+ ])
+ @endif
@@ -1515,81 +1523,120 @@
applyAccountEditMode(accountEditToggle?.checked === true);
let accountPageRequest = null;
+ const loadAccountPage = async (url) => {
+ const pageUrl = new URL(url, window.location.href);
+ pageUrl.searchParams.set('tab', 'accounts');
+ if (!accountPanel) {
+ window.location.assign(pageUrl.toString());
+ return;
+ }
+
+ const currentBody = accountPanel.querySelector('.ledger-accounts-table tbody');
+ const currentSummary = accountPanel.querySelector('.ledger-summary');
+ const currentPagination = accountPanel.querySelector('.ledger-pagination');
+ const tableWrap = accountPanel.querySelector('.ledger-accounts-table-wrap');
+ if (!currentBody || !currentSummary || !currentPagination || !tableWrap) {
+ window.location.assign(pageUrl.toString());
+ return;
+ }
+
+ const tableScrollTop = tableWrap.scrollTop;
+ const tableScrollLeft = tableWrap.scrollLeft;
+ accountPageRequest?.abort();
+ const request = new AbortController();
+ accountPageRequest = request;
+ const targetPage = pageUrl.searchParams.get('accounts_page') || '1';
+ accountPanel.setAttribute('aria-busy', 'true');
+ notify('正在加载第 ' + targetPage + ' 页…', false, true);
+ try {
+ const response = await fetch(pageUrl.toString(), {
+ credentials: 'same-origin',
+ headers: {
+ 'Accept': 'text/html',
+ 'X-Requested-With': 'XMLHttpRequest',
+ },
+ signal: request.signal,
+ });
+ if (!response.ok) throw new Error('分页加载失败(HTTP ' + response.status + ')');
+
+ const nextDocument = new DOMParser().parseFromString(await response.text(), 'text/html');
+ const nextPanel = nextDocument.querySelector('#ledger-panel-accounts');
+ const nextBody = nextPanel?.querySelector('.ledger-accounts-table tbody');
+ const nextSummary = nextPanel?.querySelector('.ledger-summary');
+ const nextPagination = nextPanel?.querySelector('.ledger-pagination');
+ if (!nextBody || !nextSummary || !nextPagination) throw new Error('分页内容解析失败');
+
+ currentBody.replaceWith(document.importNode(nextBody, true));
+ currentSummary.replaceWith(document.importNode(nextSummary, true));
+ currentPagination.replaceWith(document.importNode(nextPagination, true));
+ if (window.history?.replaceState) {
+ window.history.replaceState({ ...window.history.state, ledgerAccountsAjax: true }, '', pageUrl.toString());
+ }
+
+ const nextTableWrap = accountPanel.querySelector('.ledger-accounts-table-wrap');
+ if (nextTableWrap) {
+ nextTableWrap.scrollTop = tableScrollTop;
+ nextTableWrap.scrollLeft = tableScrollLeft;
+ }
+ bindInlineAccountSelect('[data-account-status]', 'status', '账户状态已保存');
+ bindInlineAccountSelect('[data-account-type]', 'account_type', '账户类型已保存');
+ bindInlineAccountSelect('[data-account-plan]', 'company_plan', '公司规划已保存');
+ bindInlineAccountSelect('[data-account-keep]', 'account_should_keep', '账户是否保留已保存');
+ applyAccountEditMode(accountEditToggle?.checked === true);
+ applyAccountColumnLayout();
+ bindAccountPagination();
+ notify('已加载第 ' + targetPage + ' 页');
+ } catch (error) {
+ if (error.name !== 'AbortError') {
+ const pageSelect = accountPanel.querySelector('[data-ledger-page-select]');
+ const selectedOption = pageSelect?.querySelector('option[selected]');
+ if (pageSelect && selectedOption) pageSelect.value = selectedOption.value;
+ notify(error.message || '分页加载失败', true);
+ }
+ } finally {
+ if (accountPageRequest === request) {
+ accountPanel.removeAttribute('aria-busy');
+ }
+ }
+ };
const bindAccountPagination = () => {
if (!accountPanel) return;
accountPanel.querySelectorAll('.ledger-page-box__arrow[href]').forEach((link) => {
if (link.dataset.ajaxBound === '1') return;
link.dataset.ajaxBound = '1';
- link.addEventListener('click', async (event) => {
+ link.addEventListener('click', (event) => {
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button !== 0) return;
event.preventDefault();
-
- const currentBody = accountPanel.querySelector('.ledger-accounts-table tbody');
- const currentSummary = accountPanel.querySelector('.ledger-summary');
- const currentPagination = accountPanel.querySelector('.ledger-pagination');
- const tableWrap = accountPanel.querySelector('.ledger-accounts-table-wrap');
- if (!currentBody || !currentSummary || !currentPagination || !tableWrap) {
- window.location.assign(link.href);
- return;
- }
-
- const tableScrollTop = tableWrap.scrollTop;
- const tableScrollLeft = tableWrap.scrollLeft;
- accountPageRequest?.abort();
- const request = new AbortController();
- accountPageRequest = request;
- const targetPage = new URL(link.href, window.location.href).searchParams.get('accounts_page');
- const loadingMessage = targetPage ? '正在加载第 ' + targetPage + ' 页…' : '正在加载下一页…';
- accountPanel.setAttribute('aria-busy', 'true');
- notify(loadingMessage, false, true);
- try {
- const response = await fetch(link.href, {
- credentials: 'same-origin',
- headers: {
- 'Accept': 'text/html',
- 'X-Requested-With': 'XMLHttpRequest',
- },
- signal: request.signal,
- });
- if (!response.ok) throw new Error('分页加载失败(HTTP ' + response.status + ')');
-
- const nextDocument = new DOMParser().parseFromString(await response.text(), 'text/html');
- const nextPanel = nextDocument.querySelector('#ledger-panel-accounts');
- const nextBody = nextPanel?.querySelector('.ledger-accounts-table tbody');
- const nextSummary = nextPanel?.querySelector('.ledger-summary');
- const nextPagination = nextPanel?.querySelector('.ledger-pagination');
- if (!nextBody || !nextSummary || !nextPagination) throw new Error('分页内容解析失败');
-
- currentBody.replaceWith(document.importNode(nextBody, true));
- currentSummary.replaceWith(document.importNode(nextSummary, true));
- currentPagination.replaceWith(document.importNode(nextPagination, true));
- if (window.history?.replaceState) {
- window.history.replaceState({ ...window.history.state, ledgerAccountsAjax: true }, '', link.href);
- }
-
- const nextTableWrap = accountPanel.querySelector('.ledger-accounts-table-wrap');
- if (nextTableWrap) {
- nextTableWrap.scrollTop = tableScrollTop;
- nextTableWrap.scrollLeft = tableScrollLeft;
- }
- bindInlineAccountSelect('[data-account-status]', 'status', '账户状态已保存');
- bindInlineAccountSelect('[data-account-type]', 'account_type', '账户类型已保存');
- bindInlineAccountSelect('[data-account-plan]', 'company_plan', '公司规划已保存');
- bindInlineAccountSelect('[data-account-keep]', 'account_should_keep', '账户是否保留已保存');
- applyAccountEditMode(accountEditToggle?.checked === true);
- applyAccountColumnLayout();
- bindAccountPagination();
- notify(targetPage ? '已加载第 ' + targetPage + ' 页' : '下一页已加载');
- } catch (error) {
- if (error.name !== 'AbortError') notify(error.message || '分页加载失败', true);
- } finally {
- if (accountPageRequest === request) {
- accountPanel.removeAttribute('aria-busy');
- }
- }
+ loadAccountPage(link.href);
});
});
+
+ const pageSelect = accountPanel.querySelector('[data-ledger-page-select]');
+ if (pageSelect && pageSelect.dataset.ajaxBound !== '1') {
+ pageSelect.dataset.ajaxBound = '1';
+ pageSelect.addEventListener('change', () => loadAccountPage(pageSelect.value));
+ }
};
bindAccountPagination();
+
+ page.querySelectorAll('[data-ledger-page-select]').forEach((select) => {
+ if (select.closest('#ledger-panel-accounts')) return;
+ select.addEventListener('change', () => {
+ const panel = select.closest('[data-ledger-panel]');
+ const pageUrl = new URL(select.value, window.location.href);
+ if (panel?.dataset.ledgerPanel) pageUrl.searchParams.set('tab', panel.dataset.ledgerPanel);
+ window.location.assign(pageUrl.toString());
+ });
+ });
+
+ page.querySelectorAll('[data-ledger-panel] .ledger-page-box__arrow[href]').forEach((link) => {
+ if (link.closest('#ledger-panel-accounts')) return;
+ link.addEventListener('click', (event) => {
+ const panel = link.closest('[data-ledger-panel]');
+ const pageUrl = new URL(link.href, window.location.href);
+ if (panel?.dataset.ledgerPanel) pageUrl.searchParams.set('tab', panel.dataset.ledgerPanel);
+ link.href = pageUrl.toString();
+ });
+ });
})();
diff --git a/resources/views/business/pages/financial-ledger/partials/pagination.blade.php b/resources/views/business/pages/financial-ledger/partials/pagination.blade.php
new file mode 100644
index 00000000..e0a341cb
--- /dev/null
+++ b/resources/views/business/pages/financial-ledger/partials/pagination.blade.php
@@ -0,0 +1,31 @@
+@php
+ $paginationKey = $paginationKey ?? 'page';
+ $paginationLabel = $paginationLabel ?? '数据分页';
+ $lastPage = max((int) $rows->lastPage(), 1);
+ $currentPage = min(max((int) $rows->currentPage(), 1), $lastPage);
+@endphp
+
+
diff --git a/tests/Feature/Business/FinanceLedgerAccountStatusTest.php b/tests/Feature/Business/FinanceLedgerAccountStatusTest.php
index 7a9acf45..f578f6a4 100644
--- a/tests/Feature/Business/FinanceLedgerAccountStatusTest.php
+++ b/tests/Feature/Business/FinanceLedgerAccountStatusTest.php
@@ -120,6 +120,12 @@ class FinanceLedgerAccountStatusTest extends FeatureTestCase
->assertSee('ledger-accounts-table-wrap', false)
->assertSee('ledger-pagination__controls', false)
->assertSee('ledger-page-box', false)
+ ->assertSee('data-ledger-page-select', false)
+ ->assertSee('data-ledger-pagination="accounts"', false)
+ ->assertSee('data-ledger-pagination="shops"', false)
+ ->assertSee('data-ledger-pagination="flows"', false)
+ ->assertSee('data-ledger-pagination="transactions"', false)
+ ->assertSee('data-ledger-pagination="mapping"', false)
->assertSee('1 / 1', false)
->assertSee('data-ledger-column-picker', false)
->assertSee('data-ledger-column-panel', false)
@@ -481,6 +487,7 @@ class FinanceLedgerAccountStatusTest extends FeatureTestCase
]))
->assertOk()
->assertSee('ledger-page-box', false)
+ ->assertSee('data-ledger-page-select', false)
->assertSee('aria-label="下一页"', false)
->assertSee('accounts_page=2', false)
->assertSee('accounts_short=page-test', false);