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;
}