feieContentToText($content); if ($plainText === '') { return false; } $chunks = $this->splitContent($plainText, 4500); foreach ($chunks as $chunk) { $this->printTextChunk($chunk, $shop, $orderSn); } return true; } /** * 打印标签内容(链科走文本任务,飞鹅标签指令无法直接复用) */ public function printLabelMsg($content) { $plainText = $this->feieContentToText($content); if ($plainText === '') { return false; } return $this->printTextChunk($plainText); } /** * 直接打印本地文件 */ public function printFile($filePath, $optionalArray = [], $paperSize = null) { $client = self::createClient(); $printer = $this->resolvePrinterConfig($client); $paperSize = $paperSize ?? intval(getenv('LIANKENET_PAPER_SIZE') ?: 9); return $client->addJobByPath( $printer['port'], $printer['model'], $paperSize, $filePath, $optionalArray ); } /** * 打印 HTML 页面(A4 配送单等排版页面) */ public function printHtml($html, $paperSize = null, $optionalArray = []) { $html = trim((string)$html); if ($html === '') { return false; } $tempFile = $this->createTempHtmlFile($html); try { return $this->printFile($tempFile, $optionalArray, $paperSize); } finally { if (is_file($tempFile)) { @unlink($tempFile); } } } /** * 生成可打印 HTML 临时文件 */ protected function createTempHtmlFile($html) { $tempFile = tempnam(sys_get_temp_dir(), 'lk_print_'); if ($tempFile === false) { throw new CloudPrinterApiException('无法创建临时打印文件'); } $target = $tempFile . '.html'; @unlink($tempFile); file_put_contents($target, $html); return $target; } /** * 飞鹅排版标签转纯文本 */ protected function feieContentToText($content) { $text = str_ireplace(['
', '
', '
', '
'], "\n", (string)$content); $text = preg_replace('/<\/?CB>/i', '', $text); $text = preg_replace('/<\/?B>/i', '', $text); $text = preg_replace('/<\/?C>/i', '', $text); $text = preg_replace('/.*?<\/QR>/is', '', $text); $text = preg_replace('/<[^>]+>/', '', $text); $text = str_replace(["\r\n", "\r"], "\n", $text); return trim($text); } /** * 长内容分段,避免单文件过大 */ protected function splitContent($text, $maxLength = 4500) { if (strlen($text) <= $maxLength) { return [$text]; } $lines = explode("\n", $text); $chunks = []; $current = ''; foreach ($lines as $line) { $candidate = $current === '' ? $line : $current . "\n" . $line; if (strlen($candidate) > $maxLength) { if ($current !== '') { $chunks[] = $current; } $current = $line; } else { $current = $candidate; } } if ($current !== '') { $chunks[] = $current; } return $chunks; } /** * 提交一段文本为打印任务 */ protected function printTextChunk($text, $shop = null, $orderSn = '') { $tempFile = $this->createTempTextFile($text); try { $client = self::createClient(); $printer = $this->resolvePrinterConfig($client); $paperSize = intval(getenv('LIANKENET_PAPER_SIZE') ?: 9); $client->addJobByPath( $printer['port'], $printer['model'], $paperSize, $tempFile, $this->buildOptionalParams() ); } catch (\Throwable $e) { Yii::error('链科云打印失败: ' . $e->getMessage(), __METHOD__); $shopName = ''; if (is_object($shop)) { $shopName = ($shop->merchantName ?? '') . ($shop->shopName ?? ''); } noticeUtil::push( trim($shopName . ' 链科云打印未成功,订单号:' . $orderSn . ',原因:' . $e->getMessage()), '15280215347' ); return false; } finally { if (is_file($tempFile)) { @unlink($tempFile); } } return true; } /** * 生成 UTF-8 BOM 文本临时文件,便于 Windows 打印盒识别中文 */ protected function createTempTextFile($text) { $tempFile = tempnam(sys_get_temp_dir(), 'lk_print_'); if ($tempFile === false) { throw new CloudPrinterApiException('无法创建临时打印文件'); } $target = $tempFile . '.txt'; @unlink($tempFile); file_put_contents($target, "\xEF\xBB\xBF" . $text); return $target; } /** * 解析打印机 USB 口与驱动名:优先 .env,否则取列表首台 */ protected function resolvePrinterConfig(CloudPrinter $client) { if (is_array(self::$printerConfig)) { return self::$printerConfig; } $port = trim((string)getenv('LIANKENET_DEVICE_PORT')); $model = trim((string)getenv('LIANKENET_PRINTER_MODEL')); if ($port !== '' && $model !== '') { self::$printerConfig = ['port' => $port, 'model' => $model]; return self::$printerConfig; } $list = $client->getPrinterList(); if (empty($list)) { throw new CloudPrinterApiException('链科设备下没有可用打印机'); } $printer = $list[0]; self::$printerConfig = [ 'port' => $printer->port ?? '', 'model' => $printer->driver_name ?? '', ]; if (self::$printerConfig['port'] === '' || self::$printerConfig['model'] === '') { throw new CloudPrinterApiException('链科打印机信息不完整'); } return self::$printerConfig; } /** * 可选打印参数(份数、颜色、方向等,按 v3 文档扩展) */ protected function buildOptionalParams() { $params = []; $copies = intval(getenv('LIANKENET_COPIES') ?: 1); if ($copies > 1) { $params['dmCopies'] = $copies; } return $params; } }