mirror of
https://gitee.com/ulthon/ulthon_information.git
synced 2026-07-01 16:22:49 +08:00
feat(typesetting): Wave 1 - 对齐修复+底部对齐、封面页字号豁免、字号UI改造
- 修复对齐按钮缺少click handler的缺陷,新增事件委托 - 三态对齐切换: 居顶(↑) -> 居中(↕) -> 居底(↓) - 封面页和尾页通过CSS变量重置不受全局fontScale影响 - 字号控制从slider改为dropdown+自定义输入,预设0.5/0.8/1.0/1.2/1.5/2.0
This commit is contained in:
@@ -112,6 +112,7 @@
|
|||||||
|
|
||||||
/* --- 封面页/首页 --- */
|
/* --- 封面页/首页 --- */
|
||||||
.page-cover {
|
.page-cover {
|
||||||
|
--pi-font-scale: 1 !important;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -335,6 +336,7 @@
|
|||||||
|
|
||||||
/* --- 总结页/尾页 --- */
|
/* --- 总结页/尾页 --- */
|
||||||
.page-summary {
|
.page-summary {
|
||||||
|
--pi-font-scale: 1 !important;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -417,6 +419,12 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.page-body.valign-bottom .page-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
/* ============================================
|
/* ============================================
|
||||||
Content Flow (中间栏内容流)
|
Content Flow (中间栏内容流)
|
||||||
所有元素按实际尺寸纵向排列
|
所有元素按实际尺寸纵向排列
|
||||||
|
|||||||
@@ -897,7 +897,12 @@ var PhoneImageEngine = (function () {
|
|||||||
function generateContentPage(blocks, pageNum, sizeConfig, isLast) {
|
function generateContentPage(blocks, pageNum, sizeConfig, isLast) {
|
||||||
// 读取逐页对齐配置
|
// 读取逐页对齐配置
|
||||||
var alignment = (config.pageAlignments && config.pageAlignments[pageNum]) || 'top';
|
var alignment = (config.pageAlignments && config.pageAlignments[pageNum]) || 'top';
|
||||||
var valignClass = alignment === 'center' ? ' valign-center' : '';
|
var valignClass = '';
|
||||||
|
if (alignment === 'center') {
|
||||||
|
valignClass = ' valign-center';
|
||||||
|
} else if (alignment === 'bottom') {
|
||||||
|
valignClass = ' valign-bottom';
|
||||||
|
}
|
||||||
|
|
||||||
var html = '<div class="phone-image-page page-body' + valignClass + '" style="width:' +
|
var html = '<div class="phone-image-page page-body' + valignClass + '" style="width:' +
|
||||||
sizeConfig.width + 'px;height:' + sizeConfig.height + 'px;">';
|
sizeConfig.width + 'px;height:' + sizeConfig.height + 'px;">';
|
||||||
@@ -1230,8 +1235,11 @@ var PhoneImageEngine = (function () {
|
|||||||
var pageNum = pages[i].pageNum || (i);
|
var pageNum = pages[i].pageNum || (i);
|
||||||
var currentAlign = (config.pageAlignments && config.pageAlignments[pageNum]) || 'top';
|
var currentAlign = (config.pageAlignments && config.pageAlignments[pageNum]) || 'top';
|
||||||
var isActiveCenter = currentAlign === 'center';
|
var isActiveCenter = currentAlign === 'center';
|
||||||
var $toggle = $('<button class="thumb-alignment-toggle' + (isActiveCenter ? ' active-center' : '') + '" data-page-index="' + i + '" data-page-num="' + pageNum + '">' +
|
var isActiveBottom = currentAlign === 'bottom';
|
||||||
(isActiveCenter ? '\u2195' : '\u2191') +
|
var activeClass = isActiveCenter ? ' active-center' : (isActiveBottom ? ' active-bottom' : '');
|
||||||
|
var symbol = isActiveCenter ? '\u2195' : (isActiveBottom ? '\u2193' : '\u2191');
|
||||||
|
var $toggle = $('<button class="thumb-alignment-toggle' + activeClass + '" data-page-index="' + i + '" data-page-num="' + pageNum + '">' +
|
||||||
|
symbol +
|
||||||
'</button>');
|
'</button>');
|
||||||
$item.append($toggle);
|
$item.append($toggle);
|
||||||
}
|
}
|
||||||
@@ -1580,6 +1588,26 @@ var PhoneImageEngine = (function () {
|
|||||||
return div.innerHTML;
|
return div.innerHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===== 对齐按钮事件委托 =====
|
||||||
|
$(document).on('click', '.thumb-alignment-toggle', function () {
|
||||||
|
var $btn = $(this);
|
||||||
|
var pageNum = parseInt($btn.attr('data-page-num'), 10);
|
||||||
|
var currentAlign = (config.pageAlignments && config.pageAlignments[pageNum]) || 'top';
|
||||||
|
|
||||||
|
// 三态循环: top -> center -> bottom -> top
|
||||||
|
var nextAlign;
|
||||||
|
if (currentAlign === 'top') {
|
||||||
|
nextAlign = 'center';
|
||||||
|
} else if (currentAlign === 'center') {
|
||||||
|
nextAlign = 'bottom';
|
||||||
|
} else {
|
||||||
|
nextAlign = 'top';
|
||||||
|
}
|
||||||
|
|
||||||
|
setPageAlignment(pageNum, nextAlign);
|
||||||
|
render();
|
||||||
|
});
|
||||||
|
|
||||||
// ===== 公开API =====
|
// ===== 公开API =====
|
||||||
return {
|
return {
|
||||||
init: init,
|
init: init,
|
||||||
|
|||||||
@@ -238,8 +238,17 @@
|
|||||||
<span>渲染预览</span>
|
<span>渲染预览</span>
|
||||||
<div style="display:inline-flex;align-items:center;gap:8px;float:right;">
|
<div style="display:inline-flex;align-items:center;gap:8px;float:right;">
|
||||||
<span style="font-size:12px;color:#666;">字号</span>
|
<span style="font-size:12px;color:#666;">字号</span>
|
||||||
<input type="range" id="font-scale-slider" min="0.5" max="2.0" step="0.1" value="1.0"
|
<select id="font-scale-select" style="height:26px;font-size:12px;border:1px solid #d9d9d9;border-radius:3px;padding:0 4px;">
|
||||||
style="width:100px;vertical-align:middle;">
|
<option value="0.5">0.5x</option>
|
||||||
|
<option value="0.8">0.8x</option>
|
||||||
|
<option value="1.0" selected>1.0x</option>
|
||||||
|
<option value="1.2">1.2x</option>
|
||||||
|
<option value="1.5">1.5x</option>
|
||||||
|
<option value="2.0">2.0x</option>
|
||||||
|
<option value="custom">自定义</option>
|
||||||
|
</select>
|
||||||
|
<input type="number" id="font-scale-custom" min="0.5" max="2.0" step="0.1" value="1.0"
|
||||||
|
style="width:60px;height:24px;font-size:12px;border:1px solid #d9d9d9;border-radius:3px;text-align:center;display:none;">
|
||||||
<span id="font-scale-value" style="font-size:12px;color:#1890ff;min-width:32px;">1.0x</span>
|
<span id="font-scale-value" style="font-size:12px;color:#1890ff;min-width:32px;">1.0x</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -420,27 +429,39 @@
|
|||||||
// 初始同步预览区
|
// 初始同步预览区
|
||||||
PhoneImageEngine.syncPreview();
|
PhoneImageEngine.syncPreview();
|
||||||
|
|
||||||
// 字号倍数 Slider
|
// 字号倍数 Dropdown + 自定义输入
|
||||||
var $slider = $('#font-scale-slider');
|
var $scaleSelect = $('#font-scale-select');
|
||||||
|
var $scaleCustom = $('#font-scale-custom');
|
||||||
var $scaleValue = $('#font-scale-value');
|
var $scaleValue = $('#font-scale-value');
|
||||||
|
var fontScalePresets = [0.5, 0.8, 1.0, 1.2, 1.5, 2.0];
|
||||||
|
|
||||||
// 拖动中: 仅更新CSS变量和显示值,不触发html2canvas
|
function setFontScaleUI(val) {
|
||||||
$slider.on('input', function() {
|
var $select = $('#font-scale-select');
|
||||||
var val = parseFloat($(this).val());
|
var $custom = $('#font-scale-custom');
|
||||||
|
if (fontScalePresets.indexOf(val) >= 0) {
|
||||||
|
$select.val(String(val));
|
||||||
|
$custom.hide();
|
||||||
|
} else {
|
||||||
|
$select.val('custom');
|
||||||
|
$custom.val(val).show();
|
||||||
|
}
|
||||||
|
$('#font-scale-value').text(parseFloat(val).toFixed(1) + 'x');
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyFontScaleValue(val) {
|
||||||
|
val = Math.max(0.5, Math.min(2.0, parseFloat(val) || 1.0));
|
||||||
$scaleValue.text(val.toFixed(1) + 'x');
|
$scaleValue.text(val.toFixed(1) + 'x');
|
||||||
currentConfig.fontScale = val;
|
currentConfig.fontScale = val;
|
||||||
document.getElementById('render-preview').style.setProperty('--pi-font-scale', val);
|
document.getElementById('render-preview').style.setProperty('--pi-font-scale', val);
|
||||||
var staging = document.getElementById('render-staging');
|
var staging = document.getElementById('render-staging');
|
||||||
if (staging) staging.style.setProperty('--pi-font-scale', val);
|
if (staging) staging.style.setProperty('--pi-font-scale', val);
|
||||||
PhoneImageEngine.updateConfig({ fontScale: val });
|
PhoneImageEngine.updateConfig({ fontScale: val });
|
||||||
});
|
}
|
||||||
|
|
||||||
// 松手后: 触发完整渲染(重新分页 + html2canvas截图)
|
function triggerFontScaleSave(val) {
|
||||||
$slider.on('change', function() {
|
val = parseFloat(val);
|
||||||
var val = parseFloat($(this).val());
|
|
||||||
PhoneImageLogPanel.log('字号调整为 ' + val.toFixed(1) + 'x', 'info');
|
PhoneImageLogPanel.log('字号调整为 ' + val.toFixed(1) + 'x', 'info');
|
||||||
doRender({ fontScale: val });
|
doRender({ fontScale: val });
|
||||||
// 触发保存,确保字号倍数持久化
|
|
||||||
updateSaveState('saving');
|
updateSaveState('saving');
|
||||||
PhoneImageEngine.saveConfig(postData.postId, {
|
PhoneImageEngine.saveConfig(postData.postId, {
|
||||||
size: currentConfig.size,
|
size: currentConfig.size,
|
||||||
@@ -455,12 +476,42 @@
|
|||||||
PhoneImageLogPanel.log('字号保存失败: ' + err, 'error');
|
PhoneImageLogPanel.log('字号保存失败: ' + err, 'error');
|
||||||
updateSaveState('error');
|
updateSaveState('error');
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下拉选择: 预设值直接应用,自定义则显示输入框
|
||||||
|
$scaleSelect.on('change', function() {
|
||||||
|
var selected = $(this).val();
|
||||||
|
if (selected === 'custom') {
|
||||||
|
$scaleCustom.show().focus();
|
||||||
|
} else {
|
||||||
|
$scaleCustom.hide();
|
||||||
|
var val = parseFloat(selected);
|
||||||
|
applyFontScaleValue(val);
|
||||||
|
triggerFontScaleSave(val);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 初始化时更新 Slider 显示值
|
// 自定义输入: 实时预览
|
||||||
|
$scaleCustom.on('input', function() {
|
||||||
|
var val = parseFloat($(this).val());
|
||||||
|
if (!isNaN(val) && val >= 0.5 && val <= 2.0) {
|
||||||
|
applyFontScaleValue(val);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 自定义输入: 失焦时触发保存
|
||||||
|
$scaleCustom.on('change', function() {
|
||||||
|
var val = parseFloat($(this).val());
|
||||||
|
if (isNaN(val) || val < 0.5) val = 0.5;
|
||||||
|
if (val > 2.0) val = 2.0;
|
||||||
|
$(this).val(val);
|
||||||
|
applyFontScaleValue(val);
|
||||||
|
triggerFontScaleSave(val);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 初始化时更新字号显示值
|
||||||
if (initConfig.fontScale && initConfig.fontScale !== 1) {
|
if (initConfig.fontScale && initConfig.fontScale !== 1) {
|
||||||
$slider.val(initConfig.fontScale);
|
setFontScaleUI(initConfig.fontScale);
|
||||||
$scaleValue.text(parseFloat(initConfig.fontScale).toFixed(1) + 'x');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== 设置弹框 ==========
|
// ========== 设置弹框 ==========
|
||||||
@@ -734,8 +785,7 @@
|
|||||||
if (cfg.watermark !== undefined) currentConfig.watermark = cfg.watermark;
|
if (cfg.watermark !== undefined) currentConfig.watermark = cfg.watermark;
|
||||||
if (cfg.fontScale !== undefined) {
|
if (cfg.fontScale !== undefined) {
|
||||||
currentConfig.fontScale = cfg.fontScale;
|
currentConfig.fontScale = cfg.fontScale;
|
||||||
$slider.val(cfg.fontScale);
|
setFontScaleUI(cfg.fontScale);
|
||||||
$scaleValue.text(parseFloat(cfg.fontScale).toFixed(1) + 'x');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lastOutputId = outputId;
|
lastOutputId = outputId;
|
||||||
|
|||||||
Reference in New Issue
Block a user