feat(phone-image): 添加字号倍数控制功能

- CSS: 新增 --pi-font-scale 变量,全量 font-size 支持 calc 缩放
- JS: config.fontScale 影响分页计算,applyFontScale() 同步CSS变量
- HTML: 渲染预览区 Slider 控件(0.5x~2.0x),拖动即时预览,松手完整渲染
- 后端: PhoneImage.php 新增 fontScale 配置字段和校验
- 所有保存路径(autoSave/save/generate)包含 fontScale 持久化
This commit is contained in:
augushong
2026-05-15 00:50:57 +08:00
parent 8ad90a28c0
commit 5a81385448
4 changed files with 104 additions and 38 deletions

View File

@@ -11,11 +11,13 @@
/* --- CSS Custom Properties (小红书经典风格) --- */
:root {
/* 字号缩放 */
--pi-font-scale: 1;
/* 字号 */
--pi-font-size-base: 14px;
--pi-font-size-title: 26px;
--pi-font-size-subtitle: 16px;
--pi-font-size-small: 12px;
--pi-font-size-base: calc(14px * var(--pi-font-scale, 1));
--pi-font-size-title: calc(26px * var(--pi-font-scale, 1));
--pi-font-size-subtitle: calc(16px * var(--pi-font-scale, 1));
--pi-font-size-small: calc(12px * var(--pi-font-scale, 1));
/* 行高 */
--pi-line-height: 1.8;
/* 间距 */
@@ -66,7 +68,7 @@
position: absolute;
bottom: 60px;
right: 20px;
font-size: 12px;
font-size: calc(12px * var(--pi-font-scale, 1));
color: rgba(0, 0, 0, 0.3);
pointer-events: none;
white-space: nowrap;
@@ -105,7 +107,7 @@
}
.page-cover .cover-title {
font-size: 28px;
font-size: calc(28px * var(--pi-font-scale, 1));
font-weight: normal;
letter-spacing: 2px;
line-height: 1.5;
@@ -163,7 +165,7 @@
}
.page-cover.no-cover-image .cover-no-img-title {
font-size: 36px;
font-size: calc(36px * var(--pi-font-scale, 1));
font-weight: bold;
line-height: 1.4;
color: var(--pi-color-text);
@@ -220,7 +222,7 @@
}
.page-header .page-title {
font-size: 20px;
font-size: calc(20px * var(--pi-font-scale, 1));
font-weight: normal;
letter-spacing: 1px;
color: #666;
@@ -250,7 +252,7 @@
.page-content h2 {
font-weight: normal;
font-size: 18px;
font-size: calc(18px * var(--pi-font-scale, 1));
letter-spacing: 1px;
margin-top: 24px;
margin-bottom: 12px;
@@ -259,28 +261,28 @@
.page-content h3 {
font-weight: normal;
font-size: 16px;
font-size: calc(16px * var(--pi-font-scale, 1));
margin-top: 20px;
margin-bottom: 10px;
color: #555;
}
.page-content h4 {
font-size: 14px;
font-size: calc(14px * var(--pi-font-scale, 1));
font-weight: bold;
margin-top: var(--pi-spacing-sm);
margin-bottom: 5px;
}
.page-content h5 {
font-size: 13px;
font-size: calc(13px * var(--pi-font-scale, 1));
font-weight: bold;
margin-top: var(--pi-spacing-sm);
margin-bottom: 5px;
}
.page-content h6 {
font-size: 12px;
font-size: calc(12px * var(--pi-font-scale, 1));
font-weight: bold;
margin-top: var(--pi-spacing-sm);
margin-bottom: 5px;
@@ -310,7 +312,7 @@
border-top: none;
padding-top: 0;
margin-top: var(--pi-spacing-sm);
font-size: 11px;
font-size: calc(11px * var(--pi-font-scale, 1));
color: #bbb;
display: flex;
justify-content: space-between;
@@ -330,7 +332,7 @@
.page-summary .summary-title {
font-weight: normal;
letter-spacing: 2px;
font-size: 22px;
font-size: calc(22px * var(--pi-font-scale, 1));
margin-bottom: var(--pi-spacing);
color: var(--pi-color-text);
}
@@ -447,7 +449,7 @@
border-radius: 50%;
background: var(--pi-color-accent);
color: #fff;
font-size: 14px;
font-size: calc(14px * var(--pi-font-scale, 1));
line-height: 20px;
text-align: center;
border: none;
@@ -473,7 +475,7 @@
}
.page-break-marker .break-marker-label {
font-size: 12px;
font-size: calc(12px * var(--pi-font-scale, 1));
color: #ff4d4f;
user-select: none;
}
@@ -488,7 +490,7 @@
border-radius: 50%;
background: #ff4d4f;
color: #fff;
font-size: 14px;
font-size: calc(14px * var(--pi-font-scale, 1));
line-height: 20px;
text-align: center;
border: none;
@@ -529,7 +531,7 @@
.preview-thumb-page-num {
display: block;
text-align: center;
font-size: 12px;
font-size: calc(12px * var(--pi-font-scale, 1));
color: #999;
margin-top: 6px;
}
@@ -547,7 +549,7 @@
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
font-size: calc(14px * var(--pi-font-scale, 1));
color: #666;
user-select: none;
border: none;
@@ -576,7 +578,7 @@
============================================ */
/* 表格美化样式html2canvas兼容 */
.page-content table { width: 100%; border-collapse: collapse; margin: 10px 0; font-size: 13px; }
.page-content table { width: 100%; border-collapse: collapse; margin: 10px 0; font-size: calc(13px * var(--pi-font-scale, 1)); }
.page-content th { background-color: #f0f0f0; font-weight: bold; padding: 8px 10px; border: 1px solid #ddd; text-align: left; }
.page-content td { padding: 8px 10px; border: 1px solid #ddd; }
.page-content tr:nth-child(even) td { background-color: #f9f9f9; }
@@ -587,14 +589,14 @@
border-radius: 4px;
padding: 12px;
overflow-x: auto;
font-size: 13px;
font-size: calc(13px * var(--pi-font-scale, 1));
line-height: 1.6;
margin: 10px 0;
}
.content-flow code {
font-family: 'Courier New', Consolas, monospace;
font-size: 13px;
font-size: calc(13px * var(--pi-font-scale, 1));
}
.content-flow pre code {
@@ -604,7 +606,7 @@
}
/* 中间栏表格样式 */
.content-flow-block table { width: 100%; border-collapse: collapse; margin: 10px 0; font-size: 13px; }
.content-flow-block table { width: 100%; border-collapse: collapse; margin: 10px 0; font-size: calc(13px * var(--pi-font-scale, 1)); }
.content-flow-block th { background-color: #f0f0f0; font-weight: bold; padding: 8px 10px; border: 1px solid #ddd; text-align: left; }
.content-flow-block td { padding: 8px 10px; border: 1px solid #ddd; }
.content-flow-block tr:nth-child(even) td { background-color: #f9f9f9; }
@@ -785,7 +787,7 @@ body > .page-header-right .layui-btn:not(.layui-btn-primary):not(.layui-btn-norm
/* 预览区标题字号 */
#render-preview h1 {
font-size: 22px;
font-size: calc(22px * var(--pi-font-scale, 1));
font-weight: bold;
letter-spacing: 1px;
margin-top: 24px;
@@ -795,7 +797,7 @@ body > .page-header-right .layui-btn:not(.layui-btn-primary):not(.layui-btn-norm
#render-preview h2 {
font-weight: normal;
font-size: 18px;
font-size: calc(18px * var(--pi-font-scale, 1));
letter-spacing: 1px;
margin-top: 24px;
margin-bottom: 12px;
@@ -803,27 +805,27 @@ body > .page-header-right .layui-btn:not(.layui-btn-primary):not(.layui-btn-norm
#render-preview h3 {
font-weight: normal;
font-size: 16px;
font-size: calc(16px * var(--pi-font-scale, 1));
margin-top: 20px;
margin-bottom: 10px;
}
#render-preview h4 {
font-size: 14px;
font-size: calc(14px * var(--pi-font-scale, 1));
font-weight: bold;
margin-top: 10px;
margin-bottom: 5px;
}
#render-preview h5 {
font-size: 13px;
font-size: calc(13px * var(--pi-font-scale, 1));
font-weight: bold;
margin-top: 10px;
margin-bottom: 5px;
}
#render-preview h6 {
font-size: 12px;
font-size: calc(12px * var(--pi-font-scale, 1));
font-weight: bold;
margin-top: 10px;
margin-bottom: 5px;
@@ -850,7 +852,7 @@ body > .page-header-right .layui-btn:not(.layui-btn-primary):not(.layui-btn-norm
width: 100%;
border-collapse: collapse;
margin: 10px 0;
font-size: 13px;
font-size: calc(13px * var(--pi-font-scale, 1));
}
#render-preview th {
@@ -877,14 +879,14 @@ body > .page-header-right .layui-btn:not(.layui-btn-primary):not(.layui-btn-norm
border-radius: 4px;
padding: 12px;
overflow-x: auto;
font-size: 13px;
font-size: calc(13px * var(--pi-font-scale, 1));
line-height: 1.6;
margin: 10px 0;
}
#render-preview code {
font-family: 'Courier New', Consolas, monospace;
font-size: 13px;
font-size: calc(13px * var(--pi-font-scale, 1));
}
#render-preview pre code {

View File

@@ -19,7 +19,8 @@ var PhoneImageEngine = (function () {
xiaohongshu: { width: 540, height: 720 },
douyin: { width: 540, height: 960 }
},
contentPadding: 20
contentPadding: 20,
fontScale: 1
};
// ===== 文章数据 =====
@@ -71,6 +72,15 @@ var PhoneImageEngine = (function () {
if (userConfig) {
$.extend(config, userConfig);
}
applyFontScale();
}
/**
* 应用字号缩放到CSS变量
*/
function applyFontScale() {
var scale = config.fontScale || 1;
document.documentElement.style.setProperty('--pi-font-scale', scale);
}
/**
@@ -656,7 +666,7 @@ var PhoneImageEngine = (function () {
}
// 按句子拆分:句号、问号、叹号、换行(兼容不支持 lookbehind 的浏览器)
var effectiveFontSize = 14;
var effectiveFontSize = 14 * (config.fontScale || 1);
var parts = text.split(/([。!?\n])/);
var sentences = [];
var current = '';
@@ -1269,6 +1279,7 @@ var PhoneImageEngine = (function () {
config: {
size: saveConfig.size || config.size,
watermark: saveConfig.watermark || config.watermark,
fontScale: config.fontScale || 1,
pageAlignments: config.pageAlignments || {}
},
content_html: saveConfig.content_html || postData.content_html
@@ -1488,6 +1499,7 @@ var PhoneImageEngine = (function () {
if (newConfig) {
$.extend(config, newConfig);
}
applyFontScale();
}
};
})();