新增流式 xlsx/csv 读取器与分片导入:上传建行缓存,按片处理(2 万行/25 秒预算),批量 upsert + 批量审计事件,前端进度条自动续跑;上限 20 万行,上传 50MB。
134 lines
8.2 KiB
PHP
134 lines
8.2 KiB
PHP
{{--
|
|
「终版」目录的按表页面:保留原有的导入、导出、查询、重置、编辑按钮、
|
|
导入模板和列头,数据来自该目录自己的独立数据。
|
|
--}}
|
|
@php
|
|
$finalDataset = $payablesFinal['dataset'] ?? ($page['slug'] ?? '');
|
|
$finalFields = $payablesFinal['fields'] ?? [];
|
|
$finalRows = $payablesFinal['rows'] ?? null;
|
|
$finalKeyword = $payablesFinal['keyword'] ?? '';
|
|
$finalActions = $payablesFinal['actions'] ?? '';
|
|
$finalMaintenance = ['dataset' => $finalDataset, 'fields' => $finalFields];
|
|
@endphp
|
|
|
|
<div class="payables-final-page">
|
|
<style>
|
|
.payables-final-toolbar {
|
|
display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.75rem; margin-bottom: 1rem;
|
|
padding: 1rem; border: 1px solid var(--vip-border, #D8D2C7); border-radius: 0.5rem; background: var(--vip-surface, #FFFFFF);
|
|
}
|
|
.payables-final-field { display: flex; min-width: 12rem; flex-direction: column; gap: 0.35rem; }
|
|
.payables-final-field label { color: var(--vip-content-muted, #595959); font-size: 0.75rem; font-weight: 600; }
|
|
.payables-final-field input {
|
|
height: 2.25rem; min-width: 12rem; padding: 0 0.65rem; border: 1px solid var(--vip-border, #D8D2C7);
|
|
border-radius: 0.5rem; background: var(--vip-surface, #FFFFFF); color: var(--vip-content-ink, #171717);
|
|
font-size: 0.8125rem; outline: none;
|
|
}
|
|
.payables-final-field input:focus { border-color: var(--vip-content-accent-dark, #856632); box-shadow: 0 0 0 3px rgba(133, 102, 50, .2); }
|
|
.payables-final-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; }
|
|
.payables-final-button {
|
|
display: inline-flex; height: 2.25rem; align-items: center; justify-content: center; gap: 0.35rem;
|
|
padding: 0 0.85rem; border: 1px solid var(--vip-border, #D8D2C7); border-radius: 0.5rem;
|
|
background: var(--vip-surface, #FFFFFF); color: var(--vip-content-ink, #171717);
|
|
font-size: 0.8125rem; font-weight: 600; white-space: nowrap; cursor: pointer;
|
|
}
|
|
.payables-final-button:hover, .payables-final-button:focus { border-color: var(--vip-content-accent-dark, #856632); color: var(--vip-content-accent-dark, #856632); }
|
|
.payables-final-button.is-primary { border-color: var(--vip-content-accent-dark, #856632); background: var(--vip-content-accent-dark, #856632); color: #fff; }
|
|
.payables-final-card { border: 1px solid var(--vip-border, #D8D2C7); border-radius: 0.5rem; background: var(--vip-surface, #FFFFFF); overflow: hidden; }
|
|
.payables-final-scroll { width: 100%; overflow-x: auto; }
|
|
.payables-final-table { width: max-content; min-width: 100%; border-collapse: collapse; font-size: 0.8125rem; }
|
|
.payables-final-table th, .payables-final-table td { padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--vip-border, #D8D2C7); white-space: nowrap; }
|
|
.payables-final-table thead th { background: var(--vip-content-accent-soft, #F7F0DE); color: var(--vip-content-ink, #171717); font-weight: 700; text-align: left; }
|
|
.payables-final-table .is-number { text-align: right; }
|
|
.payables-final-table .is-empty td { height: 8rem; color: var(--vip-content-muted, #595959); text-align: center; }
|
|
.payables-final-pagination { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 0.75rem 1rem; color: var(--vip-content-muted, #595959); font-size: 0.8125rem; }
|
|
</style>
|
|
|
|
<form method="GET" class="payables-final-toolbar" aria-label="{{ $page['title'] ?? '' }}筛选">
|
|
<div class="payables-final-field">
|
|
<label for="payables-final-keyword">关键词</label>
|
|
<input id="payables-final-keyword" name="keyword" type="search" value="{{ $finalKeyword }}" placeholder="按本表任意内容筛选">
|
|
</div>
|
|
<div class="payables-final-actions supplier-page-actions">
|
|
<button type="button" class="payables-final-button supplier-action-button" data-supplier-import-open>
|
|
<span class="material-icons-outlined" aria-hidden="true">upload_file</span><span>导入</span>
|
|
</button>
|
|
<a href="{{ $finalActions . '/export?' . http_build_query(request()->except('page')) }}" class="payables-final-button supplier-action-button">
|
|
<span class="material-icons-outlined" aria-hidden="true">download</span><span>导出</span>
|
|
</a>
|
|
<button type="submit" class="payables-final-button supplier-action-button is-primary">
|
|
<span class="material-icons-outlined" aria-hidden="true">search</span><span>查询</span>
|
|
</button>
|
|
<a href="{{ route('business.pages.show', ['section' => $section['slug'], 'page' => $page['slug']]) }}" class="payables-final-button supplier-action-button">
|
|
<span class="material-icons-outlined" aria-hidden="true">refresh</span><span>重置</span>
|
|
</a>
|
|
<button type="button" class="payables-final-button supplier-action-button" data-supplier-maintenance-open>
|
|
<span class="material-icons-outlined" aria-hidden="true">edit</span><span>编辑</span>
|
|
</button>
|
|
</div>
|
|
</form>
|
|
|
|
@include('business.pages.supplier-payables.maintenance-import-modal', [
|
|
'supplierImportAction' => $finalActions . '/import',
|
|
'supplierTemplateUrl' => $finalActions . '/template',
|
|
'supplierImportUploadUrl' => $finalActions . '/import-upload',
|
|
'supplierImportChunkUrl' => $finalActions . '/import-chunk',
|
|
])
|
|
|
|
<div class="payables-final-card">
|
|
<div class="payables-final-scroll">
|
|
<table class="payables-final-table">
|
|
<thead>
|
|
<tr>
|
|
<th>序号</th>
|
|
@foreach ($finalFields as $field)
|
|
<th @class(['is-number' => $field['type'] === 'number'])>{{ $field['label'] }}</th>
|
|
@endforeach
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@forelse ($finalRows ?? [] as $index => $row)
|
|
<tr data-supplier-maintenance-row data-key="{{ $row['_action_key'] ?? '' }}"
|
|
data-row="{!! e(json_encode($row, JSON_UNESCAPED_UNICODE)) !!}" tabindex="0" aria-selected="false">
|
|
<td>{{ ($finalRows->firstItem() ?? 1) + $index }}</td>
|
|
@foreach ($finalFields as $field)
|
|
@php $value = $row[$field['name']] ?? null; @endphp
|
|
<td @class(['is-number' => $field['type'] === 'number'])>
|
|
@if ($value === null || $value === '')
|
|
-
|
|
@elseif ($field['type'] === 'number' && is_numeric($value))
|
|
{{ number_format((float) $value, 2) }}
|
|
@else
|
|
{{ $value }}
|
|
@endif
|
|
</td>
|
|
@endforeach
|
|
</tr>
|
|
@empty
|
|
<tr class="is-empty">
|
|
<td colspan="{{ count($finalFields) + 1 }}">暂无数据,请点击“导入”上传本表数据。</td>
|
|
</tr>
|
|
@endforelse
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="payables-final-pagination">
|
|
<span>共 {{ $finalRows?->total() ?? 0 }} 条</span>
|
|
<span>
|
|
@if ($finalRows && ! $finalRows->onFirstPage())
|
|
<a href="{{ $finalRows->previousPageUrl() }}">上一页</a>
|
|
@endif
|
|
第 {{ $finalRows?->currentPage() ?? 1 }} 页 / 共 {{ $finalRows?->lastPage() ?? 1 }} 页
|
|
@if ($finalRows?->hasMorePages())
|
|
<a href="{{ $finalRows->nextPageUrl() }}">下一页</a>
|
|
@endif
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@include('business.pages.supplier-payables.maintenance-blade-modal', [
|
|
'content' => ['supplierPayableMaintenance' => $finalMaintenance],
|
|
'supplierMaintenanceAction' => $finalActions,
|
|
])
|