CaiWuXiTong/resources/views/business/pages/partials/final-dataset-table.blade.php
renshen 656c655c91 应付款终版导入:支持 20 万行(流式读取 + 分片导入 + 进度显示) (#361)
新增流式 xlsx/csv 读取器与分片导入:上传建行缓存,按片处理(2 万行/25 秒预算),批量 upsert + 批量审计事件,前端进度条自动续跑;上限 20 万行,上传 50MB。
2026-10-16 23:54:03 +08:00

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,
])