From 90b4b1d5f2ab1d5820f9c1fe7958744bfac0e489 Mon Sep 17 00:00:00 2001 From: augushong Date: Thu, 7 May 2026 21:53:03 +0800 Subject: [PATCH] =?UTF-8?q?refactor(phone-image):=20=E6=B8=85=E7=90=86?= =?UTF-8?q?=E6=AD=BB=E4=BB=A3=E7=A0=81=E3=80=81=E4=BF=AE=E5=A4=8D=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E8=AE=B0=E5=BD=95=E5=92=8C=E5=AA=92=E4=BD=93=E6=A0=87?= =?UTF-8?q?=E7=AD=BE=E5=AE=89=E5=85=A8=E7=A7=BB=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit T8: 删除estimateImageHeight/estimateTableHeight/showGeneratedThumbnails/switchSize/ getConfig/getPages/renderContentFlow等未使用函数,exportLongImage添加render锁检查 T9: loadFromHistory恢复pageAlignments,font_size→fontSize命名统一(PHP+JS双向兼容), 修复历史加载时fontSize显示值bug T10: preprocessContent移除iframe/video/svg/embed/object标签, 封面图添加onerror处理 --- app/common/tools/PhoneImage.php | 8 +-- public/static/js/phone-image.js | 90 ++++++-------------------------- view/admin/post/phone_image.html | 25 ++++++--- 3 files changed, 37 insertions(+), 86 deletions(-) diff --git a/app/common/tools/PhoneImage.php b/app/common/tools/PhoneImage.php index 5124c1d..a4ffe2c 100644 --- a/app/common/tools/PhoneImage.php +++ b/app/common/tools/PhoneImage.php @@ -18,7 +18,7 @@ class PhoneImage implements PostOutputManagerInterface 'template' => ['type' => 'select', 'options' => ['minimal', 'magazine', 'mixed'], 'default' => 'minimal'], 'size' => ['type' => 'select', 'options' => ['xiaohongshu', 'douyin'], 'default' => 'xiaohongshu'], 'font' => ['type' => 'select', 'options' => ['source-han-sans', 'alibaba-puhuiti', 'lxgw-wenkai'], 'default' => 'source-han-sans'], - 'font_size' => ['type' => 'number', 'default' => 14, 'min' => 10, 'max' => 24], + 'fontSize' => ['type' => 'number', 'default' => 14, 'min' => 10, 'max' => 24], 'watermark' => ['type' => 'text', 'default' => ''], ]; } @@ -39,9 +39,9 @@ class PhoneImage implements PostOutputManagerInterface if (isset($config['font']) && !in_array($config['font'], $fields['font']['options'])) { return false; } - if (isset($config['font_size'])) { - $size = intval($config['font_size']); - if ($size < $fields['font_size']['min'] || $size > $fields['font_size']['max']) { + if (isset($config['fontSize'])) { + $size = intval($config['fontSize']); + if ($size < $fields['fontSize']['min'] || $size > $fields['fontSize']['max']) { return false; } } diff --git a/public/static/js/phone-image.js b/public/static/js/phone-image.js index 1df0b65..657a30b 100644 --- a/public/static/js/phone-image.js +++ b/public/static/js/phone-image.js @@ -227,6 +227,14 @@ var PhoneImageEngine = (function () { if (!html) return ''; html = html.replace(/]*>[\s\S]*?<\/script>/gi, ''); html = html.replace(/]*>[\s\S]*?<\/style>/gi, ''); + + // 移除不支持的媒体标签 + html = html.replace(//gi, '[媒体内容]'); + html = html.replace(//gi, '[媒体内容]'); + html = html.replace(//gi, ''); + html = html.replace(/]*>/gi, ''); + html = html.replace(//gi, ''); + // 清除空段落 html = html.replace(/]*>\s*<\/p>/gi, ''); @@ -357,7 +365,6 @@ var PhoneImageEngine = (function () { block.estimatedHeight = 0; block.needsMeasurement = true; } - block.$img = $el; break; case 'ul': case 'ol': @@ -415,22 +422,6 @@ var PhoneImageEngine = (function () { return lines * hSize * 1.4 + 20; // heading行高1.4 + 20px上下间距 } - /** - * 估算图片高度 - * 默认按内容区宽度的60%估算 - */ - function estimateImageHeight($img) { - var w = parseInt($img.attr('width'), 10); - var h = parseInt($img.attr('height'), 10); - if (w > 0 && h > 0) { - // 按比例缩放到内容宽度 - var ratio = getContentWidth() / w; - return Math.round(h * ratio) + 10; - } - // 无尺寸信息时默认300px - return 310; - } - /** * 估算列表高度 */ @@ -447,15 +438,6 @@ var PhoneImageEngine = (function () { return estimateTextHeight(text, config.fontSize) + 10; } - /** - * 估算表格高度 (已废弃 - DOM实测替代) - * @deprecated 使用 measureBlockHeights() 替代 - */ - function estimateTableHeight($table) { - // DOM实测将覆盖此值,返回0作为占位 - return 0; - } - // ===== 分页核心算法 ===== /** @@ -644,7 +626,7 @@ var PhoneImageEngine = (function () { html += '" style="width:' + sizeConfig.width + 'px;height:' + sizeConfig.height + 'px;">'; if (hasCover) { - html += ''; + html += ''; html += '
' + escapeHtml(postData.title) + '
'; if (postData.desc) { html += '
' + escapeHtml(postData.desc) + '
'; @@ -1409,34 +1391,6 @@ var PhoneImageEngine = (function () { return deferred.promise(); } - /** - * 将生成的canvas数组显示为缩略图 - * @param {Array} canvases canvas对象数组 - * @param {string} containerSelector 容器选择器 - */ - function showGeneratedThumbnails(canvases, containerSelector) { - var $container = $(containerSelector); - $container.empty(); - - for (var i = 0; i < canvases.length; i++) { - var thumb = canvases[i].toDataURL('image/jpeg', 0.5); - var $item = $('
' + - '第' + (i + 1) + '页' + - '' + (i + 1) + '' + - '
'); - $container.append($item); - } - } - - // ===== 配置切换 ===== - - /** - * 切换尺寸 - */ - function switchSize(name) { - config.size = name; - } - // ===== 逐页对齐 ===== /** @@ -1456,6 +1410,13 @@ var PhoneImageEngine = (function () { */ function exportLongImage() { var deferred = $.Deferred(); + + if (render._locked) { + layer.msg('请等待渲染完成'); + deferred.reject('rendering'); + return deferred.promise(); + } + var $flow = $('#content-flow'); if (!$flow.length) { deferred.reject('内容流容器不存在'); @@ -1511,20 +1472,6 @@ var PhoneImageEngine = (function () { return div.innerHTML; } - /** - * 获取当前配置 - */ - function getConfig() { - return $.extend({}, config); - } - - /** - * 获取分页结果 - */ - function getPages() { - return pages.slice(); - } - // ===== 公开API ===== return { init: init, @@ -1532,12 +1479,7 @@ var PhoneImageEngine = (function () { generateImages: generateImages, saveImages: saveImages, saveConfig: saveConfig, - showGeneratedThumbnails: showGeneratedThumbnails, - switchSize: switchSize, - getConfig: getConfig, - getPages: getPages, setPageAlignment: setPageAlignment, - renderContentFlow: renderContentFlow, insertPageBreak: insertPageBreak, removePageBreak: removePageBreak, exportLongImage: exportLongImage diff --git a/view/admin/post/phone_image.html b/view/admin/post/phone_image.html index a11e6b9..cbf7788 100644 --- a/view/admin/post/phone_image.html +++ b/view/admin/post/phone_image.html @@ -223,15 +223,19 @@ }); var renderTimer = null; - function doRender() { + function doRender(extraConfig) { clearTimeout(renderTimer); renderTimer = setTimeout(function() { var fontSize = parseInt($('[name="fontSize"]').val()) || 14; - PhoneImageEngine.init(postData, { + var initConfig = { size: $('[name="size"]').val(), fontSize: fontSize, watermark: $('[name="watermark"]').val() - }); + }; + if (extraConfig) { + $.extend(initConfig, extraConfig); + } + PhoneImageEngine.init(postData, initConfig); var loadIdx = layer.load(); PhoneImageEngine.render().then(function(pages) { layer.close(loadIdx); @@ -377,9 +381,10 @@ $('[name="size"]').val(cfg.size); form.render('select'); } - if (cfg.fontSize) { - $('[name="fontSize"]').val(cfg.fontSize); - $('#fontSizeValue').text(cfg.fontSize + 'px'); + if (cfg.fontSize || cfg.font_size) { + var fs = cfg.fontSize || cfg.font_size; + $('[name="fontSize"]').val(fs); + $('#fontSizeValue').text(fs + 'px'); } if (cfg.watermark !== undefined) { $('[name="watermark"]').val(cfg.watermark); @@ -394,9 +399,13 @@ // 关闭历史弹窗 layer.closeAll(); - // 重新初始化引擎并渲染 + // 重新初始化引擎并渲染(恢复pageAlignments) lastOutputId = outputId; - doRender(); + var renderConfig = {}; + if (cfg.pageAlignments) { + renderConfig.pageAlignments = cfg.pageAlignments; + } + doRender(renderConfig); layer.msg('已加载历史配置'); }).fail(function () { layer.close(loadIdx2);