renshen 145a62c397 供应商对账:增加发货日期范围筛选 (#402)
内部厂家端和厂家门户增加日期面板与近7天、本月、上月、全部日期快捷筛选。
2026-10-20 11:00:43 +08:00

500 lines
33 KiB
PHP

<div class="supplier-reconciliation-page">
@php
$formatReturnQty = static function (mixed $value): string {
$quantity = (float) $value;
return number_format($quantity, abs($quantity - round($quantity)) < 0.00001 ? 0 : 2);
};
@endphp
<style>
.supplier-reconciliation-page { display: grid; gap: 16px; }
.supplier-reconciliation-page .sr-card { min-width: 0; max-width: 100%; padding: 16px; border: 1px solid var(--vip-border, #D8D2C7); border-radius: 8px; background: var(--vip-surface, #fff); display: grid; gap: 12px; }
.supplier-reconciliation-page h2 { margin: 0; font-size: .875rem; font-weight: 600; color: var(--vip-content-ink, #171717); }
.supplier-reconciliation-page .sr-toolbar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px; }
.supplier-reconciliation-page .sr-field { display: grid; gap: 4px; }
.supplier-reconciliation-page .sr-field span { color: var(--vip-content-muted, #595959); font-size: .75rem; font-weight: 600; }
.supplier-reconciliation-page select,
.supplier-reconciliation-page input[type="text"],
.supplier-reconciliation-page input[type="date"] { width: 100%; height: 36px; min-width: 0; padding: 0 10px; border: 1px solid var(--vip-border, #D8D2C7); border-radius: 8px; background: #fff; font-size: .8125rem; }
.supplier-reconciliation-page .sr-button { display: inline-flex; height: 36px; align-items: center; gap: 6px; padding: 0 14px; border: 1px solid var(--vip-border, #D8D2C7); border-radius: 8px; background: #fff; color: var(--vip-content-ink, #171717); font-size: .8125rem; font-weight: 600; text-decoration: none; cursor: pointer; }
.supplier-reconciliation-page .sr-button.is-primary { border-color: var(--vip-content-accent-dark, #856632); background: var(--vip-content-accent-dark, #856632); color: #fff; }
.supplier-reconciliation-page .sr-hint { margin: 0; color: var(--vip-content-muted, #595959); font-size: .75rem; line-height: 1.7; }
.supplier-reconciliation-page .sr-scroll { min-width: 0; max-width: 100%; overflow-x: auto; scrollbar-width: thin; }
.supplier-reconciliation-page table { width: 100%; min-width: 720px; border-collapse: collapse; font-size: .8125rem; }
.supplier-reconciliation-page th { padding: 8px 10px; background: var(--vip-content-accent-soft, #F7F0DE); border-bottom: 1px solid var(--vip-border, #D8D2C7); color: #5B5343; font-size: .75rem; font-weight: 600; text-align: left; white-space: nowrap; }
.supplier-reconciliation-page td { padding: 8px 10px; border-bottom: 1px solid #EFEAE0; }
.supplier-reconciliation-page td.is-num { text-align: right; font-variant-numeric: tabular-nums; }
.supplier-reconciliation-page .sr-muted { color: var(--vip-content-muted, #595959); }
.supplier-reconciliation-page .sr-empty { padding: 28px; border: 1px dashed var(--vip-border, #D8D2C7); border-radius: 8px; color: var(--vip-content-muted, #595959); font-size: .8125rem; text-align: center; }
.supplier-reconciliation-page .sr-upload { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.supplier-reconciliation-page .sr-pagination { display: flex; align-items: center; gap: 12px; color: var(--vip-content-muted, #595959); font-size: .8125rem; }
.supplier-reconciliation-page .sr-button.is-small { height: 24px; padding: 0 10px; font-size: .75rem; }
.supplier-reconciliation-page .sr-return-banner {
display: flex; align-items: flex-start; gap: 8px;
padding: 10px 12px; border: 1px solid #E4DCCB; border-radius: 8px;
background: var(--vip-content-accent-soft, #F7F0DE);
color: #5B5343; font-size: .8125rem; line-height: 1.7;
}
.supplier-reconciliation-page .sr-return-banner .material-icons-outlined { color: var(--vip-content-accent-dark, #856632); font-size: 18px; }
.supplier-reconciliation-page .sr-return-status { display: flex; flex-wrap: wrap; gap: 4px 10px; color: var(--vip-content-muted, #595959); font-size: .75rem; }
.supplier-reconciliation-page .sr-return-summary { display: grid; grid-template-columns: repeat(5, minmax(145px, 1fr)); gap: 12px; }
.supplier-reconciliation-page .sr-return-stat { min-width: 0; padding: 16px 18px; border: 1px solid var(--vip-border, #D8D2C7); border-radius: 10px; background: #fff; display: grid; gap: 8px; }
.supplier-reconciliation-page .sr-return-stat.is-total { border-color: #E4DCCB; background: var(--vip-content-accent-soft, #F7F0DE); }
.supplier-reconciliation-page .sr-return-stat > span { color: var(--vip-content-muted, #595959); font-size: .75rem; font-weight: 600; }
.supplier-reconciliation-page .sr-return-stat strong { color: var(--vip-content-ink, #171717); font-size: 1.375rem; font-weight: 700; line-height: 1.2; font-variant-numeric: tabular-nums; white-space: nowrap; }
.supplier-reconciliation-page .sr-return-stat strong small { margin-left: 3px; color: var(--vip-content-muted, #595959); font-size: .75rem; font-weight: 500; }
.supplier-reconciliation-page .sr-return-stat em { color: var(--vip-content-muted, #595959); font-size: .8125rem; font-style: normal; font-variant-numeric: tabular-nums; }
.supplier-reconciliation-page .sr-return-table { min-width: 1420px; }
.supplier-reconciliation-page .sr-filter { display: grid; grid-template-columns: minmax(220px, 1.6fr) repeat(2, minmax(135px, .8fr)) minmax(150px, 1fr) minmax(125px, .75fr); gap: 10px 12px; align-items: end; padding: 12px; border: 1px solid #EFEAE0; border-radius: 8px; background: #FCFAF5; }
.supplier-reconciliation-page .sr-filter-actions { display: flex; flex-wrap: wrap; gap: 8px; grid-column: 1 / -1; }
.supplier-reconciliation-page .sr-date-presets { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; grid-column: 1 / -1; margin-top: -2px; }
.supplier-reconciliation-page .sr-date-presets > span { margin-right: 2px; color: var(--vip-content-muted, #595959); font-size: .75rem; font-weight: 600; }
@media (max-width: 960px) {
.supplier-reconciliation-page .sr-filter { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.supplier-reconciliation-page .sr-return-summary { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
.supplier-reconciliation-page .sr-filter { grid-template-columns: minmax(0, 1fr); }
.supplier-reconciliation-page .sr-return-summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.supplier-reconciliation-page .sr-type-tag {
display: inline-flex; align-items: center; height: 22px; padding: 0 8px;
border-radius: 4px; background: #EFEAE0; color: #595959; font-size: .75rem; white-space: nowrap;
}
.supplier-reconciliation-page .sr-tag { display: inline-flex; align-items: center; height: 22px; padding: 0 8px; border-radius: 4px; font-size: .75rem; white-space: nowrap; }
.supplier-reconciliation-page .sr-tag.is-match { background: #ECF4EC; color: #3F7A46; }
.supplier-reconciliation-page .sr-tag.is-mismatch { background: #FBEBE9; color: #A6392F; }
.supplier-reconciliation-page .sr-tag.is-logistics { margin-left: 4px; background: #F7F0DE; color: #856632; }
.supplier-reconciliation-page .sr-tag.is-no-bookkeeping { margin-left: 4px; background: #EFEAE0; color: #595959; }
.supplier-reconciliation-page tr.is-logistics td { background: #FFFDF7; }
.supplier-reconciliation-page .sr-inline-form { display: inline-flex; }
.supplier-reconciliation-page .sr-return-actions { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.supplier-reconciliation-page .sr-return-panel > .sr-return-actions { gap: 12px; }
</style>
@if (is_string(session('success')))
<div class="biz-alert" role="status">{{ session('success') }}</div>
@endif
@if ($errors->has('import'))
<div class="biz-alert biz-alert-error" role="alert">{{ $errors->first('import') }}</div>
@endif
<div class="sr-card">
<h2>厂家对账单 · 上传与实时数据</h2>
<form method="GET" class="sr-toolbar" aria-label="查询厂家">
<label class="sr-field"><span>厂家名称</span>
<input type="search"
name="supplier"
value="{{ $supplierQuery !== '' ? $supplierQuery : $selectedSupplier }}"
list="supplier-name-options"
placeholder="输入厂家名称搜索"
autocomplete="off"
required>
<datalist id="supplier-name-options">
@foreach ($supplierNames as $supplier)
<option value="{{ $supplier }}"></option>
@endforeach
</datalist>
</label>
<button type="submit" class="sr-button is-primary">查询厂家</button>
<a href="{{ $statementTemplateUrl }}" class="sr-button">下载对账单模板</a>
</form>
@if ($supplierNotFound)
<div class="biz-alert biz-alert-error" role="alert">
未找到名为「{{ $supplierQuery }}」的厂家,请输入完整名称并从搜索建议中选择。
</div>
@endif
<p class="sr-hint">
厂家只能按模板上传(表头列名与顺序必须与模板完全一致):快递名称、快递单号、单据编号(采购单号)可以留空;
单价或金额留空时按数量自动补齐(都留空按 0,未定价行可直接导出上传);其余列必填;
不符合模板或数值格式的整份失败并提示具体行号。厂家上传成功后,下面的数据与「财务端数据」的比对结果立即更新。
</p>
@if ($selectedSupplier !== '')
<form method="POST" action="{{ $uploadUrl }}" enctype="multipart/form-data" class="sr-upload">
@csrf
<input type="hidden" name="supplier" value="{{ $selectedSupplier }}">
<input type="file" name="import" accept=".xlsx,.xls,.csv" required>
<button type="submit" class="sr-button is-primary">上传 {{ $selectedSupplier }} 的对账单</button>
</form>
@else
<div class="sr-empty">还没有可选的厂家:请先在「供应商应付(终版)→ 货款对账」导入我方结算数据,厂家按其中的供应商名称上传对账单。</div>
@endif
</div>
@if ($selectedSupplier !== '')
<div class="sr-card">
<h2>{{ $selectedSupplier }} · 上传记录</h2>
<div class="sr-scroll">
<table>
<thead>
<tr><th scope="col">上传时间</th><th scope="col">文件名</th><th scope="col">行数</th></tr>
</thead>
<tbody>
@forelse ($uploads as $upload)
<tr>
<td class="sr-muted">{{ $upload['uploaded_at'] ?? '—' }}</td>
<td>{{ $upload['filename'] ?? '—' }}</td>
<td class="is-num">{{ number_format((int) ($upload['rows'] ?? 0)) }}</td>
</tr>
@empty
<tr><td colspan="3"><div class="sr-empty">该厂家还没有上传过对账单。</div></td></tr>
@endforelse
</tbody>
</table>
</div>
</div>
<div class="sr-card">
<h2>{{ $selectedSupplier }} · 上传的对账数据(共 {{ number_format($statementTotal) }} 行)</h2>
<div class="sr-scroll">
<table>
<thead>
<tr>
<th scope="col">快递名称</th><th scope="col">快递单号</th><th scope="col">单据编号(采购单号)</th>
<th scope="col">创建时间</th><th scope="col">供应商</th><th scope="col">条码</th>
<th scope="col">规格名称</th><th scope="col">数量</th><th scope="col">单价</th><th scope="col">金额</th>
</tr>
</thead>
<tbody>
@forelse ($statementRows as $row)
<tr>
<td class="sr-muted">{{ $row['expressName'] ?? '—' }}</td>
<td class="sr-muted">{{ $row['expressNo'] ?? '—' }}</td>
<td class="sr-muted">{{ $row['purchaseNo'] ?? '—' }}</td>
<td>{{ $row['createdAt'] ?? '—' }}</td>
<td>{{ $row['supplier'] ?? '—' }}</td>
<td>{{ $row['barcode'] ?? '—' }}</td>
<td>{{ $row['skuName'] ?? '—' }}</td>
<td class="is-num">{{ $row['qty'] ?? '—' }}</td>
<td class="is-num">{{ $row['unitPrice'] ?? '—' }}</td>
<td class="is-num">{{ $row['amount'] ?? '—' }}</td>
</tr>
@empty
<tr><td colspan="10"><div class="sr-empty">暂无上传数据。</div></td></tr>
@endforelse
</tbody>
</table>
</div>
@if ($statementTotal > $perPage)
@php
$pageCount = max((int) ceil($statementTotal / $perPage), 1);
$pageStart = max(1, min($rowsPage - 4, $pageCount - 8));
$pageEnd = min($pageCount, $pageStart + 8);
$pageUrl = fn (int $number): string => route('business.pages.show', array_merge($returnPanel['filter_query'], array_filter([
'section' => $section['slug'], 'page' => $page['slug'],
'supplier' => $selectedSupplier, 'rows_page' => $number,
'return_page' => $returnPanel['page'] > 1 ? $returnPanel['page'] : null,
], static fn (mixed $value): bool => $value !== null && $value !== '')));
@endphp
<div class="sr-pagination">
<span>共 {{ number_format($statementTotal) }} 行,每页 {{ $perPage }} 行 · 第 {{ $rowsPage }} / {{ $pageCount }} 页</span>
@if ($rowsPage > 1)
<a class="sr-button is-small" href="{{ $pageUrl($rowsPage - 1) }}">上一页</a>
@endif
@if ($pageStart > 1)
<a class="sr-button is-small" href="{{ $pageUrl(1) }}">1</a>
@if ($pageStart > 2) <span>…</span> @endif
@endif
@for ($number = $pageStart; $number <= $pageEnd; $number++)
<a class="sr-button is-small {{ $number === $rowsPage ? 'is-primary' : '' }}"
@if ($number === $rowsPage) aria-current="page" @endif
href="{{ $pageUrl($number) }}">{{ $number }}</a>
@endfor
@if ($pageEnd < $pageCount)
@if ($pageEnd < $pageCount - 1) <span>…</span> @endif
<a class="sr-button is-small" href="{{ $pageUrl($pageCount) }}">{{ $pageCount }}</a>
@endif
@if ($rowsPage * $perPage < $statementTotal)
<a class="sr-button is-small" href="{{ $pageUrl($rowsPage + 1) }}">下一页</a>
@endif
</div>
@endif
</div>
<div class="sr-card sr-return-panel">
<div class="sr-return-summary" aria-label="退货汇总">
<div class="sr-return-stat is-total">
<span>退货件数</span>
<strong>{{ $formatReturnQty($returnPanel['return_qty']) }}<small>件</small></strong>
</div>
<div class="sr-return-stat is-total">
<span>退货金额</span>
<strong>¥{{ number_format($returnPanel['total_amount'], 2) }}</strong>
</div>
<div class="sr-return-stat">
<span>已确认</span>
<strong>{{ $formatReturnQty($returnPanel['confirmed_qty']) }}<small>件</small></strong>
<em>¥{{ number_format($returnPanel['confirmed_amount'], 2) }}</em>
</div>
<div class="sr-return-stat">
<span>异议中</span>
<strong>{{ $formatReturnQty($returnPanel['disputed_qty']) }}<small>件</small></strong>
<em>¥{{ number_format($returnPanel['disputed_amount'], 2) }}</em>
</div>
<div class="sr-return-stat">
<span>待确认</span>
<strong>{{ $formatReturnQty($returnPanel['pending_qty']) }}<small>件</small></strong>
<em>¥{{ number_format($returnPanel['pending_amount'], 2) }}</em>
</div>
@if ($returnPanel['accounting_summary']['logistics_rows'] > 0)
<div class="sr-return-stat">
<span>转物流记账</span>
<strong>{{ $formatReturnQty($returnPanel['accounting_summary']['logistics_qty']) }}<small>件</small></strong>
<em>¥{{ number_format($returnPanel['accounting_summary']['logistics_amount'], 2) }}</em>
</div>
@endif
</div>
<div class="sr-return-banner" role="note">
<span class="material-icons-outlined" aria-hidden="true">info</span>
<span>
<strong>① 退货扣减确认</strong>
@if ($returnPanel['is_filtered'])
(当前筛选 {{ $formatReturnQty($returnPanel['return_qty']) }} 件,退货金额 ¥{{ number_format($returnPanel['total_amount'], 2) }})。
如当前筛选结果核对无误,可点「全部确认当前筛选」;其他退货行不受影响。
@else
(共 {{ $formatReturnQty($returnPanel['return_qty']) }} 件,退货金额 ¥{{ number_format($returnPanel['total_amount'], 2) }})。
核对无误请点「全部确认无异议」;个别有问题的行,在该行单独点「异议」,复核通过前该行暂不扣减。
@endif
</span>
</div>
<form method="GET"
action="{{ route('business.pages.show', ['section' => $section['slug'], 'page' => $page['slug']]) }}"
class="sr-filter"
aria-label="查询退货明细"
data-return-filter-form>
<input type="hidden" name="supplier" value="{{ $selectedSupplier }}">
<label class="sr-field"><span>关键字</span>
<input type="text" name="return_keyword"
value="{{ $returnPanel['filters']['keyword'] }}"
maxlength="100"
placeholder="条形码 / 商品名称 / 供应商条码 / 配货单号 / 快递单号">
</label>
<label class="sr-field"><span>发货日期起</span>
<input type="date"
id="business-return-date-from"
name="return_date_from"
value="{{ $returnPanel['filters']['date_from'] }}"
title="点击选择开始日期">
</label>
<label class="sr-field"><span>发货日期止</span>
<input type="date"
id="business-return-date-to"
name="return_date_to"
value="{{ $returnPanel['filters']['date_to'] }}"
title="点击选择结束日期">
</label>
<label class="sr-field"><span>仓库名称</span>
<select name="return_warehouse">
<option value="">全部仓库</option>
@foreach ($returnWarehouses as $warehouse)
<option value="{{ $warehouse }}" @selected($returnPanel['filters']['warehouse'] === $warehouse)>{{ $warehouse }}</option>
@endforeach
</select>
</label>
<label class="sr-field"><span>确认状态</span>
<select name="return_status">
<option value="">全部状态</option>
<option value="pending" @selected($returnPanel['filters']['status'] === 'pending')>待确认</option>
<option value="confirmed" @selected($returnPanel['filters']['status'] === 'confirmed')>已确认</option>
<option value="disputed" @selected($returnPanel['filters']['status'] === 'disputed')>异议中</option>
</select>
</label>
<div class="sr-date-presets" role="group" aria-label="快捷发货日期">
<span>快捷日期</span>
<button type="button" class="sr-button is-small" data-return-date-range="last-7">近 7 天</button>
<button type="button" class="sr-button is-small" data-return-date-range="this-month">本月</button>
<button type="button" class="sr-button is-small" data-return-date-range="last-month">上月</button>
<button type="button" class="sr-button is-small" data-return-date-range="all">全部日期</button>
</div>
<div class="sr-filter-actions">
<button type="submit" class="sr-button is-primary">查询</button>
<a class="sr-button"
href="{{ route('business.pages.show', ['section' => $section['slug'], 'page' => $page['slug'], 'supplier' => $selectedSupplier]) }}">重置</a>
<a class="sr-button"
href="{{ route('business.supplier-reconciliation.returns.export', array_merge(['supplier' => $selectedSupplier], $returnPanel['filter_query'])) }}">
导出当前筛选结果
</a>
</div>
</form>
<div class="sr-scroll">
<table class="sr-return-table">
<thead>
<tr>
<th scope="col">发货时间</th><th scope="col">明细供应商</th><th scope="col">条形码</th>
<th scope="col">商品名称</th><th scope="col">发货量</th><th scope="col">单价</th>
<th scope="col">金额</th><th scope="col">供应商条码</th><th scope="col">备注</th>
<th scope="col">标题</th><th scope="col">wms配货单号</th><th scope="col">仓库名称</th>
<th scope="col">快递单号</th><th scope="col">类型</th><th scope="col">操作</th>
</tr>
</thead>
<tbody>
@forelse ($returnPanel['rows'] as $row)
<tr @class(['is-logistics' => $row['_accounting_target'] === '物流'])>
<td>{{ $row['send_time'] ?? '—' }}</td>
<td>{{ $row['supplier'] ?? '—' }}</td>
<td>{{ $row['barcode'] ?? '—' }}</td>
<td>{{ $row['sku_name'] ?? '—' }}</td>
<td class="is-num">{{ $row['qty'] ?? '—' }}</td>
<td class="is-num">{{ $row['unit_price'] ?? '—' }}</td>
<td class="is-num">{{ $row['amount'] ?? '—' }}</td>
<td>{{ $row['supplier_barcode'] ?? '—' }}</td>
<td>
{{ $row['remark'] ?? '—' }}
@if ($row['_accounting_target'] !== '厂家')
<span class="sr-tag {{ $row['_accounting_target'] === '物流' ? 'is-logistics' : 'is-no-bookkeeping' }}">{{ $row['_accounting_label'] }}</span>
@endif
@if ($row['_accounting_note'] !== '按厂家退货扣减')
<div class="sr-muted" style="font-size:.7rem">{{ $row['_accounting_note'] }}</div>
@endif
</td>
<td>{{ $row['title'] ?? '—' }}</td>
<td>{{ $row['wms_pick_no'] ?? '—' }}</td>
<td>{{ $row['warehouse'] ?? '—' }}</td>
<td>{{ $row['express_no'] ?? '—' }}</td>
<td><span class="sr-type-tag">退货</span></td>
<td>
<span class="sr-return-actions">
@if ($row['status'] === 'confirmed')
<span class="sr-tag is-match">已确认</span>
@elseif ($row['status'] === 'disputed')
<span class="sr-tag is-mismatch">异议中</span>
@else
<form method="POST" action="{{ $returnConfirmUrl }}" class="sr-inline-form">
@csrf
<input type="hidden" name="supplier" value="{{ $selectedSupplier }}">
<input type="hidden" name="key" value="{{ $row['_key'] }}">
<button type="submit" class="sr-button is-small is-primary">确认</button>
</form>
<form method="POST" action="{{ $returnDisputeUrl }}" class="sr-inline-form">
@csrf
<input type="hidden" name="supplier" value="{{ $selectedSupplier }}">
<input type="hidden" name="key" value="{{ $row['_key'] }}">
<button type="submit" class="sr-button is-small">异议</button>
</form>
@endif
</span>
</td>
</tr>
@empty
<tr><td colspan="15"><div class="sr-empty">没有符合当前查询条件的退货数据。</div></td></tr>
@endforelse
</tbody>
</table>
</div>
<p class="sr-hint">
厂家端只展示核对退货所需的字段,左右滑动查看全部。
@if ($returnPanel['is_filtered'])
当前筛选结果:{{ $formatReturnQty($returnPanel['return_qty']) }} 件,退货金额 ¥{{ number_format($returnPanel['total_amount'], 2) }},导出包含当前查询条件下的全部数据。
@else
退货共 {{ $formatReturnQty($returnPanel['return_qty']) }} 件,退货金额 ¥{{ number_format($returnPanel['total_amount'], 2) }},导出包含该厂家的全部退货数据。
@endif
按导入顺序展示,每页 {{ $returnPanel['per_page'] }} 行(第 {{ $returnPanel['page'] }} / {{ $returnPanel['pages'] }} 页)。
</p>
@if ($returnPanel['pages'] > 1)
@php
$returnPageCount = $returnPanel['pages'];
$returnPageCurrent = $returnPanel['page'];
$returnPageStart = max(1, min($returnPageCurrent - 4, $returnPageCount - 8));
$returnPageEnd = min($returnPageCount, $returnPageStart + 8);
$returnPageUrl = fn (int $number): string => route('business.pages.show', array_merge($returnPanel['filter_query'], array_filter([
'section' => $section['slug'],
'page' => $page['slug'],
'supplier' => $selectedSupplier,
'rows_page' => $rowsPage > 1 ? $rowsPage : null,
'return_page' => $number,
], static fn (mixed $value): bool => $value !== null && $value !== '')));
@endphp
<div class="sr-pagination">
<span>第 {{ $returnPageCurrent }} / {{ $returnPageCount }} 页(每页 {{ $returnPanel['per_page'] }} 行)</span>
@if ($returnPageCurrent > 1)
<a class="sr-button is-small" href="{{ $returnPageUrl($returnPageCurrent - 1) }}">上一页</a>
@endif
@if ($returnPageStart > 1)
<a class="sr-button is-small" href="{{ $returnPageUrl(1) }}">1</a>
@if ($returnPageStart > 2) <span>…</span> @endif
@endif
@for ($number = $returnPageStart; $number <= $returnPageEnd; $number++)
<a class="sr-button is-small {{ $number === $returnPageCurrent ? 'is-primary' : '' }}"
@if ($number === $returnPageCurrent) aria-current="page" @endif
href="{{ $returnPageUrl($number) }}">{{ $number }}</a>
@endfor
@if ($returnPageEnd < $returnPageCount)
@if ($returnPageEnd < $returnPageCount - 1) <span>…</span> @endif
<a class="sr-button is-small" href="{{ $returnPageUrl($returnPageCount) }}">{{ $returnPageCount }}</a>
@endif
@if ($returnPageCurrent < $returnPageCount)
<a class="sr-button is-small" href="{{ $returnPageUrl($returnPageCurrent + 1) }}">下一页</a>
@endif
</div>
@endif
<div class="sr-return-actions">
<form method="POST" action="{{ $returnConfirmAllUrl }}" class="sr-inline-form">
@csrf
<input type="hidden" name="supplier" value="{{ $selectedSupplier }}">
@foreach ($returnPanel['filter_query'] as $filterName => $filterValue)
<input type="hidden" name="{{ $filterName }}" value="{{ $filterValue }}">
@endforeach
<button type="submit" class="sr-button is-primary">
{{ $returnPanel['is_filtered'] ? '全部确认当前筛选' : '全部确认无异议' }}
</button>
</form>
<span class="sr-hint">确认后退货扣减生效,明细列入结算确认函。</span>
</div>
</div>
@endif
<script>
(() => {
const form = document.querySelector('[data-return-filter-form]');
if (!form) {
return;
}
const from = form.querySelector('#business-return-date-from');
const to = form.querySelector('#business-return-date-to');
const iso = (date) => [
date.getFullYear(),
String(date.getMonth() + 1).padStart(2, '0'),
String(date.getDate()).padStart(2, '0'),
].join('-');
[from, to].forEach((input) => {
input?.addEventListener('click', () => {
if (typeof input.showPicker === 'function') {
try {
input.showPicker();
} catch (error) {
// 浏览器已在日期面板中打开时忽略。
}
}
});
});
form.querySelectorAll('[data-return-date-range]').forEach((button) => {
button.addEventListener('click', () => {
const today = new Date();
const kind = button.dataset.returnDateRange;
if (kind === 'all') {
from.value = '';
to.value = '';
} else if (kind === 'this-month') {
from.value = iso(new Date(today.getFullYear(), today.getMonth(), 1));
to.value = iso(today);
} else if (kind === 'last-month') {
from.value = iso(new Date(today.getFullYear(), today.getMonth() - 1, 1));
to.value = iso(new Date(today.getFullYear(), today.getMonth(), 0));
} else if (kind === 'last-7') {
const start = new Date(today);
start.setDate(start.getDate() - 6);
from.value = iso(start);
to.value = iso(today);
}
form.submit();
});
});
})();
</script>
</div>