diff --git a/public/static/js/phone-image.js b/public/static/js/phone-image.js
index 657e09a..476337d 100644
--- a/public/static/js/phone-image.js
+++ b/public/static/js/phone-image.js
@@ -98,52 +98,56 @@ var PhoneImageEngine = (function () {
// 从预览区读取已预处理的内容
syncPreview();
var previewEl = document.getElementById('render-preview');
- var cleanHtml = previewEl ? previewEl.innerHTML : '';
- var blocks = parseHtmlToBlocks(cleanHtml);
- // 空内容检测
- if (blocks.length === 0) {
- $('#paginated-preview').html('
文章正文内容为空
');
- render._locked = false;
- return deferred.resolve([]).promise();
- }
+ // 等待预览区内所有图片加载完成,否则 getBoundingClientRect 测高为0
+ waitForImages(previewEl).then(function () {
+ var cleanHtml = previewEl ? previewEl.innerHTML : '';
+ var blocks = parseHtmlToBlocks(cleanHtml);
- // 封面页
- pages.push(generateCoverPage(sizeConfig));
-
- // 内容分页(使用 captureEditorBlocks,T3 会完善截图逻辑)
- captureEditorBlocks(cleanHtml, blocks, contentAreaHeight, sizeConfig).then(function(contentPages) {
- pages = pages.concat(contentPages);
-
- // 尾页
- pages.push(generateSummaryPage(sizeConfig, pages.length));
-
- // 页码 N/M
- var totalPages = pages.length;
- for (var i = 0; i < pages.length; i++) {
- if (pages[i].type === 'content') {
- pages[i].html = pages[i].html.replace(
- '' + pages[i].pageNum + '',
- '' + (i + 1) + '/' + totalPages + ''
- );
- }
+ // 空内容检测
+ if (blocks.length === 0) {
+ $('#paginated-preview').html('文章正文内容为空
');
+ render._locked = false;
+ return deferred.resolve([]).promise();
}
- // 渲染缩略图
- renderThumbnails(sizeConfig).then(function() {
- render._locked = false;
- if (render._pending) {
- render._pending = false;
- render().catch(function() {});
+ // 封面页
+ pages.push(generateCoverPage(sizeConfig));
+
+ // 内容分页
+ captureEditorBlocks(cleanHtml, blocks, contentAreaHeight, sizeConfig).then(function(contentPages) {
+ pages = pages.concat(contentPages);
+
+ // 尾页
+ pages.push(generateSummaryPage(sizeConfig, pages.length));
+
+ // 页码 N/M
+ var totalPages = pages.length;
+ for (var i = 0; i < pages.length; i++) {
+ if (pages[i].type === 'content') {
+ pages[i].html = pages[i].html.replace(
+ '' + pages[i].pageNum + '',
+ '' + (i + 1) + '/' + totalPages + ''
+ );
+ }
}
- deferred.resolve(pages);
+
+ // 渲染缩略图
+ renderThumbnails(sizeConfig).then(function() {
+ render._locked = false;
+ if (render._pending) {
+ render._pending = false;
+ render().catch(function() {});
+ }
+ deferred.resolve(pages);
+ }).catch(function(err) {
+ render._locked = false;
+ deferred.reject(err);
+ });
}).catch(function(err) {
render._locked = false;
deferred.reject(err);
});
- }).catch(function(err) {
- render._locked = false;
- deferred.reject(err);
});
return deferred.promise();
@@ -204,6 +208,44 @@ var PhoneImageEngine = (function () {
$('#render-preview').html(cleanHtml);
}
+ /**
+ * 等待容器内所有图片加载完成
+ * 图片未加载时 getBoundingClientRect() 高度为0,导致分页计算错误
+ * @param {HTMLElement} containerEl
+ * @returns {jQuery Deferred}
+ */
+ function waitForImages(containerEl) {
+ var deferred = $.Deferred();
+ var imgs = containerEl ? containerEl.querySelectorAll('img') : [];
+ if (imgs.length === 0) {
+ return deferred.resolve().promise();
+ }
+ var loaded = 0;
+ var total = imgs.length;
+ var timer = setTimeout(function () {
+ // 超时保底:3秒后强制继续
+ deferred.resolve();
+ }, 3000);
+
+ function checkDone() {
+ loaded++;
+ if (loaded >= total) {
+ clearTimeout(timer);
+ deferred.resolve();
+ }
+ }
+
+ for (var i = 0; i < imgs.length; i++) {
+ if (imgs[i].complete && imgs[i].naturalHeight > 0) {
+ checkDone();
+ } else {
+ imgs[i].onload = checkDone;
+ imgs[i].onerror = checkDone;
+ }
+ }
+ return deferred.promise();
+ }
+
/**
* 将HTML解析为块级元素数组
* 每个块: { type, html, estimatedHeight }
@@ -392,30 +434,21 @@ var PhoneImageEngine = (function () {
var previewChildren = Array.prototype.slice.call(previewEl.children);
- // 逐组测高
+ // 逐 block 精确测高(包含 margin,否则分页偏小导致内容溢出)
for (var gi = 0; gi < groups.length; gi++) {
var group = groups[gi];
- var groupHeight = 0;
- for (var j = 0; j < group.domIndices.length; j++) {
+ for (var j = 0; j < group.blocks.length; j++) {
var di = group.domIndices[j];
if (di < previewChildren.length) {
- var rect = previewChildren[di].getBoundingClientRect();
- groupHeight += Math.round(rect.height);
+ var el = previewChildren[di];
+ var rect = el.getBoundingClientRect();
+ var cs = window.getComputedStyle(el);
+ var mt = parseFloat(cs.marginTop) || 0;
+ var mb = parseFloat(cs.marginBottom) || 0;
+ group.blocks[j].estimatedHeight = Math.round(rect.height + mt + mb);
}
}
-
- if (groupHeight === 0) groupHeight = group.blocks.length * 40;
-
- // 按比例分配测量的实际高度给组内各个 block
- var totalEstimated = 0;
- for (var k = 0; k < group.blocks.length; k++) {
- totalEstimated += (group.blocks[k].estimatedHeight || 40);
- }
- for (var k = 0; k < group.blocks.length; k++) {
- var ratio = (group.blocks[k].estimatedHeight || 40) / (totalEstimated || 1);
- group.blocks[k].estimatedHeight = Math.round(groupHeight * ratio);
- }
}
// 给尚未设置高度的 block 设默认值