feat: update report detail and verification flow
This commit is contained in:
@@ -6,49 +6,59 @@ class ReportPdfGenerator
|
||||
{
|
||||
public function generate(array $payload): string
|
||||
{
|
||||
$content = $this->buildContentStream($payload);
|
||||
$heroImage = $this->normalizeHeroImage($payload['hero_image'] ?? null);
|
||||
$content = $this->buildContentStream($payload, $heroImage);
|
||||
$resources = '<< /Font << /F1 5 0 R >>';
|
||||
if ($heroImage) {
|
||||
$resources .= ' /XObject << /Im1 7 0 R >>';
|
||||
}
|
||||
$resources .= ' >>';
|
||||
|
||||
$objects = [
|
||||
1 => '<< /Type /Catalog /Pages 2 0 R >>',
|
||||
2 => '<< /Type /Pages /Kids [3 0 R] /Count 1 >>',
|
||||
3 => '<< /Type /Page /Parent 2 0 R /MediaBox [0 0 595 842] /Resources << /Font << /F1 5 0 R >> >> /Contents 4 0 R >>',
|
||||
3 => sprintf('<< /Type /Page /Parent 2 0 R /MediaBox [0 0 595 842] /Resources %s /Contents 4 0 R >>', $resources),
|
||||
4 => sprintf("<< /Length %d >>\nstream\n%s\nendstream", strlen($content), $content),
|
||||
5 => '<< /Type /Font /Subtype /Type0 /BaseFont /STSong-Light /Encoding /UniGB-UCS2-H /DescendantFonts [6 0 R] >>',
|
||||
6 => '<< /Type /Font /Subtype /CIDFontType0 /BaseFont /STSong-Light /CIDSystemInfo << /Registry (Adobe) /Ordering (GB1) /Supplement 4 >> /DW 1000 >>',
|
||||
];
|
||||
if ($heroImage) {
|
||||
$objects[7] = sprintf(
|
||||
"<< /Type /XObject /Subtype /Image /Width %d /Height %d /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter /DCTDecode /Length %d >>\nstream\n%s\nendstream",
|
||||
$heroImage['width'],
|
||||
$heroImage['height'],
|
||||
strlen($heroImage['data']),
|
||||
$heroImage['data']
|
||||
);
|
||||
}
|
||||
|
||||
return $this->renderPdf($objects);
|
||||
}
|
||||
|
||||
private function buildContentStream(array $payload): string
|
||||
private function buildContentStream(array $payload, ?array $heroImage): string
|
||||
{
|
||||
$title = $this->normalizeText((string)($payload['report_title'] ?? '鉴定报告'));
|
||||
$serviceProviderText = $this->normalizeText((string)($payload['service_provider_text'] ?? '-'));
|
||||
$institutionName = $this->normalizeText((string)($payload['institution_name'] ?? '-'));
|
||||
$reportNo = $this->normalizeText((string)($payload['report_no'] ?? '-'));
|
||||
$publishTime = $this->normalizeText((string)($payload['publish_time'] ?? '-'));
|
||||
$resultText = $this->normalizeText((string)($payload['result_text'] ?? '-'));
|
||||
$resultDesc = $this->normalizeText((string)($payload['result_desc'] ?? '-'));
|
||||
$productName = $this->normalizeText((string)($payload['product_name'] ?? '-'));
|
||||
$categoryBrand = $this->normalizeText((string)($payload['category_brand'] ?? '-'));
|
||||
$specInfo = $this->normalizeText((string)($payload['spec_info'] ?? '-'));
|
||||
$appraisers = $this->normalizeText((string)($payload['appraisers'] ?? '-'));
|
||||
$conditionGrade = $this->normalizeText((string)($payload['condition_grade'] ?? '-'));
|
||||
$valuationRange = $this->normalizeText((string)($payload['valuation_range'] ?? '-'));
|
||||
$verifyInfo = $this->normalizeText((string)($payload['verify_info'] ?? '-'));
|
||||
$riskNotice = $this->normalizeText((string)($payload['risk_notice_text'] ?? '-'));
|
||||
$productItems = is_array($payload['product_items'] ?? null) ? $payload['product_items'] : [];
|
||||
$heroImageLabels = is_array($payload['hero_image_labels'] ?? null) ? $payload['hero_image_labels'] : [];
|
||||
|
||||
$blocks = [];
|
||||
$y = 790;
|
||||
|
||||
$blocks[] = $this->textBlock($title, 52, $y, 20);
|
||||
$y -= 32;
|
||||
$blocks[] = $this->textBlock('正式报告凭证,请以编号验真结果为准。', 52, $y, 10);
|
||||
$blocks[] = $this->textBlock('正式报告凭证,请以报告页防伪查询结果为准。', 52, $y, 10);
|
||||
$y -= 30;
|
||||
|
||||
foreach ([
|
||||
sprintf('报告编号:%s', $reportNo),
|
||||
sprintf('出具机构:%s', $institutionName),
|
||||
sprintf('检测机构:%s', $institutionName),
|
||||
sprintf('出具时间:%s', $publishTime),
|
||||
sprintf('服务类型:%s', $serviceProviderText),
|
||||
] as $line) {
|
||||
@@ -56,29 +66,56 @@ class ReportPdfGenerator
|
||||
$y -= 22;
|
||||
}
|
||||
|
||||
$y -= 8;
|
||||
$blocks[] = $this->textBlock(sprintf('鉴定结论:%s', $resultText), 52, $y, 16);
|
||||
$y -= 26;
|
||||
|
||||
foreach ($this->wrapText('结果说明:' . $resultDesc, 30) as $line) {
|
||||
$blocks[] = $this->textBlock($line, 52, $y, 11);
|
||||
$y -= 18;
|
||||
if ($heroImage) {
|
||||
$maxWidth = 230;
|
||||
$maxHeight = 150;
|
||||
$scale = min($maxWidth / $heroImage['width'], $maxHeight / $heroImage['height'], 1);
|
||||
$drawWidth = (int)round($heroImage['width'] * $scale);
|
||||
$drawHeight = (int)round($heroImage['height'] * $scale);
|
||||
$y -= $drawHeight + 6;
|
||||
$blocks[] = $this->imageBlock('Im1', 52, $y, $drawWidth, $drawHeight);
|
||||
$y -= 24;
|
||||
} elseif ($heroImageLabels) {
|
||||
foreach ($this->wrapText('鉴定图片:' . implode('、', array_slice($heroImageLabels, 0, 3)), 34) as $line) {
|
||||
$blocks[] = $this->textBlock($line, 52, $y, 11);
|
||||
$y -= 18;
|
||||
}
|
||||
$y -= 8;
|
||||
}
|
||||
|
||||
$y -= 8;
|
||||
foreach ([
|
||||
sprintf('商品名称:%s', $productName),
|
||||
sprintf('品类 / 品牌:%s', $categoryBrand),
|
||||
sprintf('颜色 / 规格:%s', $specInfo),
|
||||
sprintf('鉴定师:%s', $appraisers),
|
||||
sprintf('成色评级:%s', $conditionGrade),
|
||||
sprintf('估值区间:%s', $valuationRange),
|
||||
sprintf('验真信息:%s', $verifyInfo),
|
||||
] as $line) {
|
||||
$blocks[] = $this->textBlock($line, 52, $y, 11);
|
||||
$y -= 20;
|
||||
$blocks[] = $this->textBlock('产品信息', 52, $y, 15);
|
||||
$y -= 24;
|
||||
$blocks[] = $this->textBlock(sprintf('产品名称:%s', $productName), 52, $y, 12);
|
||||
$y -= 22;
|
||||
|
||||
foreach ($productItems as $item) {
|
||||
if (!is_array($item)) {
|
||||
continue;
|
||||
}
|
||||
$label = $this->normalizeText((string)($item['label'] ?? ''));
|
||||
if ($label === '') {
|
||||
continue;
|
||||
}
|
||||
$value = $this->normalizeText((string)($item['value'] ?? '-'));
|
||||
$remark = $this->normalizeText((string)($item['remark'] ?? ''));
|
||||
foreach ($this->wrapText(sprintf('%s:%s', $label, $value !== '' ? $value : '-'), 34) as $line) {
|
||||
$blocks[] = $this->textBlock($line, 52, $y, 11);
|
||||
$y -= 18;
|
||||
}
|
||||
if ($remark !== '') {
|
||||
foreach ($this->wrapText('说明:' . $remark, 34) as $line) {
|
||||
$blocks[] = $this->textBlock($line, 72, $y, 10);
|
||||
$y -= 16;
|
||||
}
|
||||
}
|
||||
$y -= 2;
|
||||
}
|
||||
|
||||
$y -= 6;
|
||||
$blocks[] = $this->textBlock(sprintf('验真信息:%s', $verifyInfo), 52, $y, 11);
|
||||
$y -= 22;
|
||||
|
||||
$y -= 8;
|
||||
foreach ($this->wrapText('风险说明:' . $riskNotice, 30) as $line) {
|
||||
$blocks[] = $this->textBlock($line, 52, $y, 10);
|
||||
@@ -86,12 +123,32 @@ class ReportPdfGenerator
|
||||
}
|
||||
|
||||
if ($y > 48) {
|
||||
$blocks[] = $this->textBlock('安心验鉴定平台', 52, 42, 9);
|
||||
$blocks[] = $this->textBlock('安心检验鉴定平台', 52, 42, 9);
|
||||
}
|
||||
|
||||
return implode("\n", array_filter($blocks));
|
||||
}
|
||||
|
||||
private function normalizeHeroImage(mixed $image): ?array
|
||||
{
|
||||
if (!is_array($image)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$data = (string)($image['data'] ?? '');
|
||||
$width = (int)($image['width'] ?? 0);
|
||||
$height = (int)($image['height'] ?? 0);
|
||||
if ($data === '' || $width <= 0 || $height <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
'data' => $data,
|
||||
'width' => $width,
|
||||
'height' => $height,
|
||||
];
|
||||
}
|
||||
|
||||
private function wrapText(string $text, int $maxUnits): array
|
||||
{
|
||||
$normalized = $this->normalizeText($text);
|
||||
@@ -137,6 +194,11 @@ class ReportPdfGenerator
|
||||
);
|
||||
}
|
||||
|
||||
private function imageBlock(string $name, int $x, int $y, int $width, int $height): string
|
||||
{
|
||||
return sprintf("q\n%d 0 0 %d %d %d cm\n/%s Do\nQ", $width, $height, $x, $y, $name);
|
||||
}
|
||||
|
||||
private function normalizeText(string $text): string
|
||||
{
|
||||
$text = trim(str_replace(["\r\n", "\r", "\n", "\t"], [' ', ' ', ' ', ' '], $text));
|
||||
|
||||
Reference in New Issue
Block a user