buildContentStream($payload); $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 >>', 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 >>', ]; return $this->renderPdf($objects); } private function buildContentStream(array $payload): 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'] ?? '-')); $blocks = []; $y = 790; $blocks[] = $this->textBlock($title, 52, $y, 20); $y -= 32; $blocks[] = $this->textBlock('正式报告凭证,请以编号验真结果为准。', 52, $y, 10); $y -= 30; foreach ([ sprintf('报告编号:%s', $reportNo), sprintf('出具机构:%s', $institutionName), sprintf('出具时间:%s', $publishTime), sprintf('服务类型:%s', $serviceProviderText), ] as $line) { $blocks[] = $this->textBlock($line, 52, $y, 12); $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; } $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; } $y -= 8; foreach ($this->wrapText('风险说明:' . $riskNotice, 30) as $line) { $blocks[] = $this->textBlock($line, 52, $y, 10); $y -= 17; } if ($y > 48) { $blocks[] = $this->textBlock('安心验鉴定平台', 52, 42, 9); } return implode("\n", array_filter($blocks)); } private function wrapText(string $text, int $maxUnits): array { $normalized = $this->normalizeText($text); if ($normalized === '') { return ['-']; } $chars = preg_split('//u', $normalized, -1, PREG_SPLIT_NO_EMPTY) ?: []; $lines = []; $current = ''; $width = 0.0; foreach ($chars as $char) { $charWidth = strlen($char) === 1 && ord($char) < 128 ? 0.5 : 1.0; if ($current !== '' && $width + $charWidth > $maxUnits) { $lines[] = $current; $current = ''; $width = 0.0; } $current .= $char; $width += $charWidth; } if ($current !== '') { $lines[] = $current; } return $lines ?: ['-']; } private function textBlock(string $text, int $x, int $y, int $fontSize): string { if ($text === '') { return ''; } return sprintf( "BT\n/F1 %d Tf\n1 0 0 1 %d %d Tm\n<%s> Tj\nET", $fontSize, $x, $y, strtoupper(bin2hex(mb_convert_encoding($text, 'UCS-2BE', 'UTF-8'))) ); } private function normalizeText(string $text): string { $text = trim(str_replace(["\r\n", "\r", "\n", "\t"], [' ', ' ', ' ', ' '], $text)); return preg_replace('/\s+/u', ' ', $text) ?: ''; } private function renderPdf(array $objects): string { $pdf = "%PDF-1.4\n%\xE2\xE3\xCF\xD3\n"; $offsets = []; foreach ($objects as $id => $body) { $offsets[$id] = strlen($pdf); $pdf .= sprintf("%d 0 obj\n%s\nendobj\n", $id, $body); } $xrefPosition = strlen($pdf); $pdf .= sprintf("xref\n0 %d\n", count($objects) + 1); $pdf .= "0000000000 65535 f \n"; foreach ($objects as $id => $_body) { $pdf .= sprintf("%010d 00000 n \n", $offsets[$id]); } $pdf .= sprintf( "trailer\n<< /Size %d /Root 1 0 R >>\nstartxref\n%d\n%%%%EOF", count($objects) + 1, $xrefPosition ); return $pdf; } }