From e8a38f493e17c70acb2ffa586826ec415c40e010 Mon Sep 17 00:00:00 2001 From: "WIN-C27C5MSVTPO\\16961" <1696136552@qq.com> Date: Tue, 16 Dec 2025 14:48:18 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/controller/SkuController.php | 78 +++++++++++--------------- 1 file changed, 33 insertions(+), 45 deletions(-) diff --git a/app/admin/controller/SkuController.php b/app/admin/controller/SkuController.php index bffb8cf..8f420fe 100644 --- a/app/admin/controller/SkuController.php +++ b/app/admin/controller/SkuController.php @@ -264,10 +264,10 @@ class SkuController extends BaseController return ''; } - // 1. 加载 docx - $phpWord = WordIOFactory::load($docxPath, 'Word2007'); + // 1. 读取 docx + $phpWord = WordIOFactory::load($docxPath); - // 2. 临时目录(非常重要) + // 2. 导出 HTML $tmpDir = runtime_path('tmp/' . uniqid()); if (!is_dir($tmpDir)) { mkdir($tmpDir, 0755, true); @@ -275,40 +275,40 @@ class SkuController extends BaseController $tmpHtml = $tmpDir . '/index.html'; - // 3. 导出 HTML $writer = WordIOFactory::createWriter($phpWord, 'HTML'); $writer->save($tmpHtml); $html = file_get_contents($tmpHtml); - // 4. 清洗 Word 垃圾 HTML(关键) + // 3. 只取 body 内容(关键) + if (preg_match('/]*>(.*?)<\/body>/is', $html, $m)) { + $html = $m[1]; + } + + // 4. 清洗 Word 垃圾样式(关键) $html = $this->cleanWordHtml($html); + // 5. 处理图片并上传 OSS $uploadService = new UploadService(); - // 5. 处理图片 $html = preg_replace_callback( '/]+src="([^"]+)"[^>]*>/i', function ($matches) use ($tmpDir, $uploadService) { $src = $matches[1]; - // 只处理本地图片 - if (preg_match('#^(http|https|data:)#i', $src)) { - return $matches[0]; + // Word 导出的是相对路径 + if (!str_starts_with($src, 'http')) { + $localImg = $tmpDir . '/' . ltrim($src, '/'); + if (is_file($localImg)) { + $ossUrl = $uploadService->uploadLocalFile([ + 'path' => $localImg, + 'scene' => 'desc' + ]); + return preg_replace('/src="[^"]+"/', 'src="' . $ossUrl . '"', $matches[0]); + } } - $localImg = realpath($tmpDir . '/' . $src); - if (!$localImg || !is_file($localImg)) { - return $matches[0]; - } - - // 上传 OSS - $ossUrl = $uploadService->uploadLocalFile([ - 'path' => $localImg, - 'scene' => 'desc' - ]); - - return str_replace($src, $ossUrl, $matches[0]); + return $matches[0]; }, $html ); @@ -319,44 +319,32 @@ class SkuController extends BaseController return trim($html); } - function deleteDir(string $dir) + function deleteDir(string $dir): void { if (!is_dir($dir)) return; foreach (scandir($dir) as $file) { if ($file === '.' || $file === '..') continue; $path = $dir . '/' . $file; - is_dir($path) ? $this->deleteDir($path) : unlink($path); + is_dir($path) ? deleteDir($path) : @unlink($path); } - rmdir($dir); + @rmdir($dir); } function cleanWordHtml(string $html): string { - // 删除 Word 注释 - $html = preg_replace('//', '', $html); - - // 删除 style / meta / link - $html = preg_replace('/<(style|meta|link)[^>]*>.*?<\/\1>/is', '', $html); - - // 删除 xml 标签 - $html = preg_replace('/.*?<\/xml>/is', '', $html); - - // 删除 mso-xxx 样式 + // 移除 Office 命名空间、样式 $html = preg_replace('/\s*mso-[^:]+:[^;"]+;?/i', '', $html); + $html = preg_replace('/\s*class="[^"]*"/i', '', $html); + $html = preg_replace('/\s*style="[^"]*"/i', '', $html); - // 清理 class="Mso..." - $html = preg_replace('/class="Mso[^"]*"/i', '', $html); + // 移除多余标签 + $html = preg_replace('/<(\/?)(html|head|meta|link|span|font|xml|o:p)[^>]*>/i', '', $html); - // 删除空 span - $html = preg_replace('/]*>\s*<\/span>/i', '', $html); + // 清理空段落 + $html = preg_replace('/

\s*<\/p>/i', '', $html); - // 删除 Office 条件注释 - $html = preg_replace('/.*?/is', '', $html); - - // 只保留 body 内容 - if (preg_match('/]*>(.*?)<\/body>/is', $html, $m)) { - $html = $m[1]; - } + // 规范段落 + $html = str_replace(['

', '

'], ["

", "

\n"], $html); return $html; }