diff --git a/public/static/css/phone-image-templates.css b/public/static/css/phone-image-templates.css index f6dcb96..7f2a4fd 100644 --- a/public/static/css/phone-image-templates.css +++ b/public/static/css/phone-image-templates.css @@ -1096,3 +1096,126 @@ body > .page-header-right .layui-btn:not(.layui-btn-primary):not(.layui-btn-norm color: #888; margin-right: 8px; } + +/* ============================================ + DOM Page Container (DOM分页预览容器) + 右侧分页预览区使用纯DOM渲染,不依赖截图 + JS动态填充这些容器 + ============================================ */ + +/* --- DOM分页容器基础 --- */ +.dom-page-container { + background: #ffffff; + overflow: hidden; + position: relative; + box-sizing: border-box; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +/* 尺寸 - 复用size class模式 */ +.size-xiaohongshu .dom-page-container { + width: 540px; + height: 720px; +} + +.size-douyin .dom-page-container { + width: 540px; + height: 960px; +} + +/* --- DOM分页品牌标识头 --- */ +.dom-page-brand-header { + height: 36px; + display: flex; + align-items: center; + padding: 0 20px; + font-size: 13px; + border-bottom: 1px solid #f0f0f0; + flex-shrink: 0; +} + +.dom-page-brand-header img { + height: 20px; + margin-right: 8px; +} + +.dom-page-brand-header span { + color: #666; +} + +/* --- DOM分页内容区域 --- */ +.dom-page-content { + padding: 20px; + overflow: hidden; + box-sizing: border-box; + height: calc(100% - 36px - 30px); + font-size: calc(14px * var(--pi-font-scale, 1)); + line-height: 1.8; + word-break: break-word; +} + +/* DOM分页内容区对齐支持 (复用valign模式) */ +.dom-page-content.valign-center { + display: flex; + flex-direction: column; + justify-content: center; +} + +.dom-page-content.valign-bottom { + display: flex; + flex-direction: column; + justify-content: flex-end; +} + +/* --- DOM分页页码 --- */ +.dom-page-footer { + position: absolute; + bottom: 0; + left: 0; + right: 0; + text-align: center; + padding: 6px 0; + font-size: 11px; + color: #999; + border-top: 1px solid #f5f5f5; + background: #fff; +} + +/* --- 纯图片页 --- */ +.dom-page-pure-image .dom-page-content { + display: flex; + align-items: center; + justify-content: center; + padding: 0; +} + +.dom-page-pure-image .dom-page-content img { + max-width: 100%; + height: auto; + display: block; +} + +/* ============================================ + DOM分页内容区代码块样式 + 参照 #render-preview pre (L926-935) + ============================================ */ +.dom-page-content pre { + background: #f6f8fa; + border-radius: 6px; + padding: 12px 16px; + overflow-x: auto; + font-size: calc(13px * var(--pi-code-font-scale, 1)); + line-height: 1.6; + margin: 10px 0; +} + +.dom-page-content code { + font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; + font-size: calc(13px * var(--pi-code-font-scale, 1)); +} + +.dom-page-content pre code { + background: none; + padding: 0; + border-radius: 0; +} diff --git a/public/static/js/phone-image.js b/public/static/js/phone-image.js index 3064f68..fd413c6 100644 --- a/public/static/js/phone-image.js +++ b/public/static/js/phone-image.js @@ -100,9 +100,15 @@ var PhoneImageEngine = (function () { }, contentPadding: 20, fontScale: 1, - tableFontScale: 1 + tableFontScale: 1, + useDomPreview: true }; + // ===== DOM分页预览状态 ===== + var domPages = []; + var currentDomPageIndex = 0; + var totalDomPages = 0; + // ===== 文章数据 ===== var postData = { id: 0, @@ -248,19 +254,30 @@ var PhoneImageEngine = (function () { } // 渲染缩略图 - renderThumbnails(sizeConfig).then(function() { - PhoneImageLogPanel.log('渲染完成,共 ' + pages.length + ' 页', 'success'); + if (config.useDomPreview) { + renderDomPages(); + PhoneImageLogPanel.log('DOM预览渲染完成,共 ' + pages.length + ' 页', 'success'); render._locked = false; if (render._pending) { render._pending = false; render().catch(function() {}); } deferred.resolve(pages); - }).catch(function(err) { - PhoneImageLogPanel.log('渲染失败: ' + err, 'error'); - render._locked = false; - deferred.reject(err); - }); + } else { + renderThumbnails(sizeConfig).then(function() { + PhoneImageLogPanel.log('渲染完成,共 ' + pages.length + ' 页', 'success'); + render._locked = false; + if (render._pending) { + render._pending = false; + render().catch(function() {}); + } + deferred.resolve(pages); + }).catch(function(err) { + PhoneImageLogPanel.log('渲染失败: ' + err, 'error'); + render._locked = false; + deferred.reject(err); + }); + } }).catch(function(err) { PhoneImageLogPanel.log('分页计算失败: ' + err, 'error'); render._locked = false; @@ -1311,6 +1328,68 @@ var PhoneImageEngine = (function () { return deferred.promise(); } + /** + * DOM分页预览 - 将pages[]转换为domPages格式 + * 替代canvas截图方案,直接操作DOM渲染 + */ + function renderDomPages() { + var sizeConfig = config.sizes[config.size] || config.sizes.xiaohongshu; + + // 清空domPages + domPages = []; + + // 如果没有pages数据,返回 + if (!pages || pages.length === 0) { + return; + } + + // 遍历pages,创建domPage对象 + for (var i = 0; i < pages.length; i++) { + var page = pages[i]; + var domPage = { + html: page.html || '', + type: page.type || 'content', + pageNum: page.pageNum || (i + 1), + valign: (config.pageAlignments && config.pageAlignments[i]) || 'top', + isPureImage: page.type === 'pure-image' + }; + domPages.push(domPage); + } + + totalDomPages = domPages.length; + currentDomPageIndex = 0; + + // 调用渲染 + renderDomPageThumbnails(sizeConfig); + } + + /** + * DOM分页预览 - 渲染所有页面的缩略图 + * TODO: T3将实现完整逻辑 + * 当前只清空容器并创建占位 + * @param {Object} sizeConfig + */ + function renderDomPageThumbnails(sizeConfig) { + var $preview = $('#paginated-preview'); + $preview.empty(); + // 完整实现在T3中 + } + + /** + * DOM分页预览 - 刷新指定页面的对齐方式 + * TODO: T3将实现完整逻辑 + * @param {number} pageIndex - 页面索引(0-based) + */ + function refreshDomPage(pageIndex) { + var $containers = $('#paginated-preview .dom-page-container'); + if (pageIndex >= 0 && pageIndex < $containers.length) { + var $content = $containers.eq(pageIndex).find('.dom-page-content'); + $content.removeClass('valign-top valign-center valign-bottom'); + var alignment = config.pageAlignments[pageIndex] || 'top'; + $content.addClass('valign-' + alignment); + } + } + /** * 初始化缩略图容器(流式渲染第一步:清空容器) * @param {Object} sizeConfig @@ -1735,6 +1814,9 @@ var PhoneImageEngine = (function () { syncPreview: syncPreview, setPageAlignment: setPageAlignment, exportLongImage: exportLongImage, + renderDomPages: renderDomPages, + renderDomPageThumbnails: renderDomPageThumbnails, + refreshDomPage: refreshDomPage, logPanel: PhoneImageLogPanel, getContentHtml: function () { if (window.phoneImageEditor) { diff --git a/view/admin/post/phone_image.html b/view/admin/post/phone_image.html index 4f7ba16..a3bd978 100644 --- a/view/admin/post/phone_image.html +++ b/view/admin/post/phone_image.html @@ -261,16 +261,16 @@
- +
- 画布预览 + 分页预览
-
+