两个「终版」目录(供应商应付(终版)、快递应付(终版))改为独立数据: 保留原有导入、导出、查询、重置、编辑按钮和导入模板,数据初始为空、按表独立存放, 不再借用基础目录的页面与数据。 - 终版目录拥有自己的同名子页面与横向页签 - 新增终版按表数据的独立导入/导出/模板/编辑接口(数据集键 final:<目录>:<页面>) - 供应商终版 13 个页面、快递终版 4 个页面已接入 - 终版导入模板统一增加“月份”列,记录标识列改为选填
92 lines
4.6 KiB
PHP
92 lines
4.6 KiB
PHP
<?php
|
||
|
||
namespace Modules\EcommerceFinance\Services;
|
||
|
||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||
use PhpOffice\PhpSpreadsheet\Style\Alignment;
|
||
use PhpOffice\PhpSpreadsheet\Style\Border;
|
||
use PhpOffice\PhpSpreadsheet\Style\Fill;
|
||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||
|
||
class SupplierPayableImportTemplate
|
||
{
|
||
/** @param array<string,array{label:string,type:string}> $fields */
|
||
public function download(string $title, array $fields, bool $optionalRecordKey = false): StreamedResponse
|
||
{
|
||
return response()->streamDownload(function () use ($title, $fields, $optionalRecordKey): void {
|
||
$spreadsheet = new Spreadsheet();
|
||
$sheet = $spreadsheet->getActiveSheet();
|
||
$sheet->setTitle($this->sheetTitle($title));
|
||
|
||
$headers = array_merge(['记录标识'], array_column($fields, 'label'));
|
||
$sheet->fromArray($headers, null, 'A1');
|
||
$lastColumn = Coordinate::stringFromColumnIndex(count($headers));
|
||
$headerRange = 'A1:' . $lastColumn . '1';
|
||
|
||
$sheet->getStyle($headerRange)->applyFromArray([
|
||
'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']],
|
||
'fill' => ['fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => '856632']],
|
||
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER, 'vertical' => Alignment::VERTICAL_CENTER],
|
||
'borders' => ['allBorders' => ['borderStyle' => Border::BORDER_THIN, 'color' => ['rgb' => 'D8D2C7']]],
|
||
]);
|
||
$sheet->getRowDimension(1)->setRowHeight(24);
|
||
$sheet->freezePane('A2');
|
||
$sheet->setAutoFilter($headerRange);
|
||
$sheet->getColumnDimension('A')->setWidth(38);
|
||
|
||
$columnIndex = 2;
|
||
foreach ($fields as $definition) {
|
||
$column = Coordinate::stringFromColumnIndex($columnIndex);
|
||
$width = max(14, min(30, mb_strlen($definition['label']) * 2 + 4));
|
||
$sheet->getColumnDimension($column)->setWidth($width);
|
||
if ($definition['type'] === 'number') {
|
||
$sheet->getStyle($column . '2:' . $column . '10001')->getNumberFormat()->setFormatCode('0.0000');
|
||
} else {
|
||
$sheet->getStyle($column . '2:' . $column . '10001')->getNumberFormat()->setFormatCode('@');
|
||
}
|
||
$columnIndex++;
|
||
}
|
||
$sheet->getStyle('A2:A10001')->getNumberFormat()->setFormatCode('@');
|
||
|
||
$instructions = $spreadsheet->createSheet();
|
||
$instructions->setTitle('填写说明');
|
||
$instructions->fromArray([
|
||
['项目', '说明'],
|
||
['记录标识', $optionalRecordKey
|
||
? '选填。留空表示新增一行;需要修改已导入的行时,请先导出、修改后再导入。'
|
||
: '必填。请从本页面导出的文件中复制,不能修改。'],
|
||
['日期', '请填写 YYYY-MM-DD,例如 2026-09-17。'],
|
||
['月份', '请填写 YYYY-MM,例如 2026-09。'],
|
||
['数字', '最多支持 4 位小数;金额可直接填写数字。'],
|
||
['空白单元格', '导入后将清空该字段,请确认后再导入。'],
|
||
], null, 'A1');
|
||
$instructions->getStyle('A1:B1')->applyFromArray([
|
||
'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']],
|
||
'fill' => ['fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => '856632']],
|
||
]);
|
||
$instructions->getColumnDimension('A')->setWidth(18);
|
||
$instructions->getColumnDimension('B')->setWidth(58);
|
||
$instructions->getStyle('A1:B6')->getAlignment()->setVertical(Alignment::VERTICAL_CENTER)->setWrapText(true);
|
||
foreach (range(1, 6) as $row) {
|
||
$instructions->getRowDimension($row)->setRowHeight($row === 1 ? 24 : 32);
|
||
}
|
||
|
||
$spreadsheet->setActiveSheetIndex(0);
|
||
(new Xlsx($spreadsheet))->save('php://output');
|
||
$spreadsheet->disconnectWorksheets();
|
||
}, $title . '_导入模板_' . now()->format('Ymd') . '.xlsx', [
|
||
'Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||
'Cache-Control' => 'private, no-store',
|
||
]);
|
||
}
|
||
|
||
private function sheetTitle(string $title): string
|
||
{
|
||
$title = str_replace(['\\', '/', '?', '*', '[', ']', ':'], '', $title) ?: '导入模板';
|
||
|
||
return mb_substr($title, 0, 31);
|
||
}
|
||
}
|