mirror of
https://gitee.com/ulthon/ulthon_information.git
synced 2026-07-01 18:32:48 +08:00
refactor(phone-image): 清理死代码、修复历史记录和媒体标签安全移除
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处理
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,6 +227,14 @@ var PhoneImageEngine = (function () {
|
||||
if (!html) return '';
|
||||
html = html.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '');
|
||||
html = html.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '');
|
||||
|
||||
// 移除不支持的媒体标签
|
||||
html = html.replace(/<iframe[\s\S]*?<\/iframe>/gi, '[媒体内容]');
|
||||
html = html.replace(/<video[\s\S]*?<\/video>/gi, '[媒体内容]');
|
||||
html = html.replace(/<svg[\s\S]*?<\/svg>/gi, '');
|
||||
html = html.replace(/<embed[^>]*>/gi, '');
|
||||
html = html.replace(/<object[\s\S]*?<\/object>/gi, '');
|
||||
|
||||
// 清除空段落
|
||||
html = html.replace(/<p[^>]*>\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 += '<img class="cover-image" src="' + escapeHtml(postData.poster) + '" alt="">';
|
||||
html += '<img class="cover-image" src="' + escapeHtml(postData.poster) + '" alt="" onerror="this.style.display=\'none\'">';
|
||||
html += '<div class="cover-title">' + escapeHtml(postData.title) + '</div>';
|
||||
if (postData.desc) {
|
||||
html += '<div class="cover-subtitle">' + escapeHtml(postData.desc) + '</div>';
|
||||
@@ -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 = $('<div class="phone-thumb-item" data-index="' + i + '">' +
|
||||
'<img src="' + thumb + '" alt="第' + (i + 1) + '页">' +
|
||||
'<span class="phone-thumb-page">' + (i + 1) + '</span>' +
|
||||
'</div>');
|
||||
$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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user