update at 2025-10-10 19:13:38
This commit is contained in:
@@ -61,4 +61,6 @@
|
||||
|
||||
现在分页依据真实渲染高度,预览窗口内不会再丢失底部内容。建议在小红书预览里多翻几页、调整字号后重新分页验证结果。
|
||||
|
||||
## v1.3.9
|
||||
重构xhs和wechat布局,统一使用grid,便于维护。
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
* 4. 提供文章导出HTML功能
|
||||
*/
|
||||
|
||||
import { Notice, Platform, TFile, TFolder } from 'obsidian';
|
||||
import { Notice, Platform, TFile } from 'obsidian';
|
||||
import { NMPSettings } from '../settings';
|
||||
import AssetsManager from '../assets';
|
||||
import { ArticleRender } from '../article-render';
|
||||
@@ -32,8 +32,9 @@ export class WechatPreview {
|
||||
currentHighlight: string;
|
||||
|
||||
// UI 元素
|
||||
toolbar: HTMLDivElement | null = null;
|
||||
renderDiv: HTMLDivElement | null = null;
|
||||
board: HTMLDivElement | null = null;
|
||||
contentCell: HTMLElement | null = null;
|
||||
contentEl: HTMLElement | null = null;
|
||||
wechatSelect: HTMLSelectElement | null = null;
|
||||
themeSelect: HTMLSelectElement | null = null;
|
||||
highlightSelect: HTMLSelectElement | null = null;
|
||||
@@ -65,97 +66,95 @@ export class WechatPreview {
|
||||
*/
|
||||
build(): void {
|
||||
this.container.empty();
|
||||
|
||||
// 创建工具栏
|
||||
this.toolbar = this.container.createDiv({ cls: 'preview-toolbar' });
|
||||
this.buildToolbar(this.toolbar);
|
||||
|
||||
// 创建渲染区域
|
||||
this.renderDiv = this.container.createDiv({ cls: 'render-div' });
|
||||
this.renderDiv.id = 'render-div';
|
||||
this.container.addClass('wechat-preview-container');
|
||||
|
||||
// 将 ArticleRender 的 style 与内容节点挂载
|
||||
try {
|
||||
if (this.render && this.render.styleEl && !this.renderDiv.contains(this.render.styleEl)) {
|
||||
this.renderDiv.appendChild(this.render.styleEl);
|
||||
}
|
||||
if (this.render && this.render.articleDiv && !this.renderDiv.contains(this.render.articleDiv)) {
|
||||
// 容器样式:模拟公众号编辑器宽度,更好的排版显示
|
||||
this.render.articleDiv.addClass('wechat-article-wrapper');
|
||||
this.renderDiv.appendChild(this.render.articleDiv);
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('[WechatPreview] 挂载文章容器失败', e);
|
||||
}
|
||||
this.board = this.container.createDiv({ cls: 'wechat-board' });
|
||||
|
||||
this.buildAccountRow();
|
||||
|
||||
//this.buildCoverRow();
|
||||
//this.buildStyleRow();
|
||||
|
||||
this.contentCell = this.createCell('content');
|
||||
this.contentCell.addClass('wechat-cell-content');
|
||||
|
||||
this.mountArticle(this.board);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建工具栏
|
||||
*/
|
||||
private buildToolbar(parent: HTMLDivElement): void {
|
||||
// 单层 Grid:所有控件直接挂到 parent(.preview-toolbar)
|
||||
private createCell(area: string, tag: keyof HTMLElementTagNameMap = 'div', extraClasses: string[] = []): HTMLElement {
|
||||
if (!this.board) {
|
||||
throw new Error('Wechat board not initialized');
|
||||
}
|
||||
const cell = this.board.createEl(tag, { attr: { 'data-area': area } });
|
||||
cell.addClass('wechat-cell');
|
||||
for (const cls of extraClasses) {
|
||||
cell.addClass(cls);
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
|
||||
// 公众号选择
|
||||
if (this.settings.wxInfo.length > 1 || Platform.isDesktop) {
|
||||
const wxLabel = parent.createDiv({ cls: 'style-label' });
|
||||
wxLabel.innerText = '公众号';
|
||||
private buildAccountRow(): void {
|
||||
const selectCell = this.createCell('account-select');
|
||||
const selectLabel = selectCell.createEl('label', {
|
||||
cls: 'style-label',
|
||||
attr: { for: 'wechat-account-select' },
|
||||
text: '公众号'
|
||||
});
|
||||
selectLabel.addClass('wechat-account-label');
|
||||
|
||||
const wxSelect = parent.createEl('select', { cls: 'wechat-select' });
|
||||
wxSelect.onchange = async () => {
|
||||
this.currentAppId = wxSelect.value;
|
||||
this.onAppIdChanged();
|
||||
const wxSelect = selectCell.createEl('select', {
|
||||
cls: 'wechat-select',
|
||||
attr: { id: 'wechat-account-select' }
|
||||
}) as HTMLSelectElement;
|
||||
wxSelect.onchange = async () => {
|
||||
this.currentAppId = wxSelect.value;
|
||||
this.onAppIdChanged();
|
||||
};
|
||||
|
||||
const defaultOp = wxSelect.createEl('option');
|
||||
defaultOp.value = '';
|
||||
defaultOp.text = '请在设置里配置公众号';
|
||||
|
||||
for (let i = 0; i < this.settings.wxInfo.length; i++) {
|
||||
const op = wxSelect.createEl('option');
|
||||
const wx = this.settings.wxInfo[i];
|
||||
op.value = wx.appid;
|
||||
op.text = wx.name;
|
||||
if (i === 0) {
|
||||
op.selected = true;
|
||||
this.currentAppId = wx.appid;
|
||||
}
|
||||
}
|
||||
this.wechatSelect = wxSelect;
|
||||
|
||||
const actionsCell = this.createCell('account-back-export');
|
||||
if (Platform.isDesktop) {
|
||||
const openBtn = actionsCell.createEl('button', {
|
||||
text: '访问后台',
|
||||
cls: 'toolbar-button purple-gradient wechat-action-button'
|
||||
});
|
||||
openBtn.onclick = async () => {
|
||||
const { shell } = require('electron');
|
||||
shell.openExternal('https://mp.weixin.qq.com');
|
||||
uevent('open-mp');
|
||||
};
|
||||
|
||||
const defaultOp = wxSelect.createEl('option');
|
||||
defaultOp.value = '';
|
||||
defaultOp.text = '请在设置里配置公众号';
|
||||
|
||||
for (let i = 0; i < this.settings.wxInfo.length; i++) {
|
||||
const op = wxSelect.createEl('option');
|
||||
const wx = this.settings.wxInfo[i];
|
||||
op.value = wx.appid;
|
||||
op.text = wx.name;
|
||||
if (i === 0) {
|
||||
op.selected = true;
|
||||
this.currentAppId = wx.appid;
|
||||
}
|
||||
}
|
||||
this.wechatSelect = wxSelect;
|
||||
|
||||
if (Platform.isDesktop) {
|
||||
//parent.createDiv({ cls: 'toolbar-separator' });
|
||||
const openBtn = parent.createEl('button', { text: '🌐 去公众号后台', cls: 'toolbar-button purple-gradient' });
|
||||
openBtn.onclick = async () => {
|
||||
const { shell } = require('electron');
|
||||
shell.openExternal('https://mp.weixin.qq.com');
|
||||
uevent('open-mp');
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 操作按钮(直接平铺在 Grid 中)
|
||||
if (Platform.isDesktop && this.settings.isAuthKeyVaild()) {
|
||||
const htmlBtn = parent.createEl('button', { text: '💾 导出HTML', cls: 'toolbar-button' });
|
||||
htmlBtn.onclick = async () => await this.exportHTML();
|
||||
const exportBtn = actionsCell.createEl('button', { text: '导出页面', cls: 'toolbar-button wechat-action-button' });
|
||||
exportBtn.onclick = async () => await this.exportHTML();
|
||||
}
|
||||
|
||||
// 封面选择
|
||||
//this.buildCoverSelector(parent);
|
||||
|
||||
// 样式选择(如果启用)
|
||||
if (this.settings.showStyleUI) {
|
||||
this.buildStyleSelector(parent);
|
||||
if (actionsCell.childElementCount === 0) {
|
||||
actionsCell.addClass('wechat-cell-placeholder');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建封面选择器
|
||||
*/
|
||||
private buildCoverSelector(parent: HTMLDivElement): void {
|
||||
const coverTitle = parent.createDiv({ cls: 'style-label' });
|
||||
coverTitle.innerText = '封面';
|
||||
private buildCoverRow(): void {
|
||||
const selectCell = this.createCell('cover-select');
|
||||
selectCell.createDiv({ cls: 'style-label', text: '封面' });
|
||||
|
||||
this.useDefaultCover = parent.createEl('input', { cls: 'input-style' });
|
||||
this.useDefaultCover = selectCell.createEl('input', { cls: 'input-style' }) as HTMLInputElement;
|
||||
this.useDefaultCover.setAttr('type', 'radio');
|
||||
this.useDefaultCover.setAttr('name', 'cover');
|
||||
this.useDefaultCover.setAttr('value', 'default');
|
||||
@@ -166,43 +165,42 @@ export class WechatPreview {
|
||||
this.coverEl.setAttr('style', 'visibility:hidden;width:0px;');
|
||||
}
|
||||
};
|
||||
selectCell.createEl('label', { text: '默认', attr: { for: 'default-cover' } });
|
||||
|
||||
const defaultLabel = parent.createEl('label');
|
||||
defaultLabel.innerText = '默认';
|
||||
defaultLabel.setAttr('for', 'default-cover');
|
||||
|
||||
this.useLocalCover = parent.createEl('input', { cls: 'input-style' });
|
||||
this.useLocalCover = selectCell.createEl('input', { cls: 'input-style' }) as HTMLInputElement;
|
||||
this.useLocalCover.setAttr('type', 'radio');
|
||||
this.useLocalCover.setAttr('name', 'cover');
|
||||
this.useLocalCover.setAttr('value', 'local');
|
||||
this.useLocalCover.id = 'local-cover';
|
||||
this.useLocalCover.setAttr('style', 'margin-left:20px;');
|
||||
this.useLocalCover.onchange = async () => {
|
||||
if (this.useLocalCover?.checked && this.coverEl) {
|
||||
this.coverEl.setAttr('style', 'visibility:visible;width:180px;');
|
||||
}
|
||||
};
|
||||
selectCell.createEl('label', { text: '上传', attr: { for: 'local-cover' } });
|
||||
|
||||
const localLabel = parent.createEl('label');
|
||||
localLabel.setAttr('for', 'local-cover');
|
||||
localLabel.innerText = '上传';
|
||||
|
||||
this.coverEl = parent.createEl('input', { cls: 'upload-input' });
|
||||
this.coverEl.setAttr('type', 'file');
|
||||
this.coverEl.setAttr('placeholder', '封面图片');
|
||||
this.coverEl.setAttr('accept', '.png, .jpg, .jpeg');
|
||||
this.coverEl.setAttr('name', 'cover');
|
||||
this.coverEl.id = 'cover-input';
|
||||
const inputCell = this.createCell('cover-input');
|
||||
this.coverEl = inputCell.createEl('input', {
|
||||
cls: 'upload-input',
|
||||
attr: {
|
||||
type: 'file',
|
||||
placeholder: '封面图片',
|
||||
accept: '.png, .jpg, .jpeg',
|
||||
name: 'cover',
|
||||
id: 'cover-input'
|
||||
}
|
||||
}) as HTMLInputElement;
|
||||
if (this.useDefaultCover?.checked) {
|
||||
this.coverEl.setAttr('style', 'visibility:hidden;width:0px;');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建样式选择器
|
||||
*/
|
||||
private buildStyleSelector(parent: HTMLDivElement): void {
|
||||
const cssStyle = parent.createDiv({ cls: 'style-label' });
|
||||
cssStyle.innerText = '样式';
|
||||
private buildStyleRow(): void {
|
||||
const styleLabelCell = this.createCell('style-label', 'div', ['style-label']);
|
||||
styleLabelCell.setText('样式');
|
||||
|
||||
const selectBtn = parent.createEl('select', { cls: 'style-select' });
|
||||
const styleSelectCell = this.createCell('style-select');
|
||||
const selectBtn = styleSelectCell.createEl('select', { cls: 'style-select wechat-style-select' }) as HTMLSelectElement;
|
||||
selectBtn.onchange = async () => {
|
||||
this.currentTheme = selectBtn.value;
|
||||
this.render.updateStyle(selectBtn.value);
|
||||
@@ -216,12 +214,11 @@ export class WechatPreview {
|
||||
}
|
||||
this.themeSelect = selectBtn;
|
||||
|
||||
parent.createDiv({ cls: 'toolbar-separator' });
|
||||
const highlightLabelCell = this.createCell('highlight-label', 'div', ['style-label']);
|
||||
highlightLabelCell.setText('代码高亮');
|
||||
|
||||
const highlightStyle = parent.createDiv({ cls: 'style-label' });
|
||||
highlightStyle.innerText = '代码高亮';
|
||||
|
||||
const highlightStyleBtn = parent.createEl('select', { cls: 'style-select' });
|
||||
const highlightSelectCell = this.createCell('highlight-select');
|
||||
const highlightStyleBtn = highlightSelectCell.createEl('select', { cls: 'style-select wechat-style-select' }) as HTMLSelectElement;
|
||||
highlightStyleBtn.onchange = async () => {
|
||||
this.currentHighlight = highlightStyleBtn.value;
|
||||
this.render.updateHighLight(highlightStyleBtn.value);
|
||||
@@ -237,6 +234,29 @@ export class WechatPreview {
|
||||
this.highlightSelect = highlightStyleBtn;
|
||||
}
|
||||
|
||||
private mountArticle(_parent: HTMLElement): void {
|
||||
if (!this.contentCell) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (this.render?.styleEl && !this.contentCell.contains(this.render.styleEl)) {
|
||||
this.contentCell.appendChild(this.render.styleEl);
|
||||
}
|
||||
if (this.render?.articleDiv) {
|
||||
this.render.articleDiv.addClass('wechat-article-wrapper');
|
||||
if (this.render.articleDiv.parentElement !== this.contentCell) {
|
||||
this.contentCell.appendChild(this.render.articleDiv);
|
||||
}
|
||||
this.contentEl = this.render.articleDiv;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('[WechatPreview] 挂载文章容器失败', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建封面选择器
|
||||
*/
|
||||
/**
|
||||
* 显示微信预览视图
|
||||
*/
|
||||
@@ -360,8 +380,9 @@ export class WechatPreview {
|
||||
* 清理资源
|
||||
*/
|
||||
destroy(): void {
|
||||
this.toolbar = null;
|
||||
this.renderDiv = null;
|
||||
this.board = null;
|
||||
this.contentCell = null;
|
||||
this.contentEl = null;
|
||||
this.wechatSelect = null;
|
||||
this.themeSelect = null;
|
||||
this.highlightSelect = null;
|
||||
|
||||
173
styles.css
173
styles.css
@@ -84,22 +84,14 @@
|
||||
.wechat-preview-container:not([style*="display: none"]),
|
||||
.xiaohongshu-preview-container:not([style*="display: none"]) {
|
||||
flex: 1;
|
||||
display: grid !important;
|
||||
grid-template-rows: auto 1fr;
|
||||
display: flex !important;
|
||||
min-height: 0; /* 允许内部滚动区域正确计算高度 */
|
||||
}
|
||||
|
||||
.render-div {
|
||||
overflow-y: auto;
|
||||
padding: 10px;
|
||||
-webkit-user-select: text;
|
||||
user-select: text;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
/* 文章包裹:模拟公众号编辑器阅读宽度 */
|
||||
.wechat-article-wrapper {
|
||||
max-width: 720px;
|
||||
width: 100%;
|
||||
max-width: clamp(360px, 80vw, 760px);
|
||||
margin: 0 auto;
|
||||
padding: 12px 18px 80px 18px; /* 底部留白方便滚动到底部操作 */
|
||||
box-sizing: border-box;
|
||||
@@ -110,19 +102,6 @@
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.preview-toolbar {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, max-content));
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
min-height: auto;
|
||||
padding: 8px 12px;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
background: var(--grad-toolbar);
|
||||
box-shadow: var(--shadow-overlay);
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
margin-right: 10px;
|
||||
padding: 6px 14px;
|
||||
@@ -312,23 +291,6 @@ label:hover { color: var(--c-primary); }
|
||||
/* Toolbar 行样式 */
|
||||
/* =========================================================== */
|
||||
|
||||
.toolbar-line {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 8px 12px;
|
||||
background: white;
|
||||
border-radius: 6px;
|
||||
margin: 8px 10px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.toolbar-line.flex-wrap {
|
||||
grid-auto-flow: row;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, max-content));
|
||||
}
|
||||
|
||||
.platform-selector-line {
|
||||
background: linear-gradient(135deg, #fff3e0 0%, #ffffff 100%) !important;
|
||||
border-left: 4px solid var(--c-primary);
|
||||
@@ -367,13 +329,125 @@ label:hover { color: var(--c-primary); }
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* =========================================================== */
|
||||
/* 微信公众号预览布局 */
|
||||
/* =========================================================== */
|
||||
|
||||
.wechat-preview-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
padding: 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.wechat-board {
|
||||
flex: 1;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, minmax(0, 1fr));
|
||||
grid-template-rows: auto auto auto minmax(0, 1fr);
|
||||
grid-template-areas:
|
||||
"account-select account-select account-select account-back-export account-back-export account-back-export"
|
||||
"cover-select cover-select cover-select cover-select cover-input cover-input"
|
||||
"style-label style-select highlight-label highlight-select highlight-select highlight-select"
|
||||
"content content content content content content";
|
||||
gap: 5px;
|
||||
background: var(--grad-toolbar);
|
||||
border-radius: 12px;
|
||||
padding: 5px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.wechat-cell {
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
padding: 12px 16px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.wechat-cell[data-area="account-select"] {
|
||||
grid-area: account-select;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.wechat-cell[data-area="account-back-export"] {
|
||||
grid-area: account-back-export;
|
||||
justify-content: flex-center;
|
||||
}
|
||||
|
||||
.wechat-cell[data-area="account-select"] .style-label {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.wechat-cell[data-area="account-select"] .wechat-select {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wechat-cell[data-area="account-back-export"] .wechat-action-button { white-space: nowrap; }
|
||||
|
||||
.wechat-cell[data-area="cover-select"] {
|
||||
grid-area: cover-select;
|
||||
justify-content: flex-start;
|
||||
gap: 18px;
|
||||
}
|
||||
.wechat-cell[data-area="cover-input"] { grid-area: cover-input; }
|
||||
|
||||
.wechat-cell[data-area="cover-select"] label {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.wechat-cell[data-area="cover-input"] .upload-input {
|
||||
margin-left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wechat-cell[data-area="style-label"] { grid-area: style-label; white-space: nowrap; justify-content: flex-start; }
|
||||
.wechat-cell[data-area="style-select"] { grid-area: style-select; width: 100%; }
|
||||
.wechat-cell[data-area="highlight-label"] { grid-area: highlight-label; white-space: nowrap; justify-content: flex-start; }
|
||||
.wechat-cell[data-area="highlight-select"] { grid-area: highlight-select; width: 100%; }
|
||||
|
||||
.wechat-cell[data-area="style-select"] .style-select,
|
||||
.wechat-cell[data-area="style-select"] .wechat-style-select,
|
||||
.wechat-cell[data-area="highlight-select"] .style-select,
|
||||
.wechat-cell[data-area="highlight-select"] .wechat-style-select {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.wechat-cell[data-area="content"] {
|
||||
grid-area: content;
|
||||
overflow-y: auto;
|
||||
padding: 10px;
|
||||
-webkit-user-select: text;
|
||||
user-select: text;
|
||||
min-height: 0;
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
display: block;
|
||||
}
|
||||
|
||||
.wechat-cell-placeholder {
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.wechat-cell-placeholder .toolbar-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* =========================================================== */
|
||||
/* 微信公众号选择器样式 */
|
||||
/* =========================================================== */
|
||||
|
||||
.wechat-select {
|
||||
padding: 6px 12px;
|
||||
min-width: 200px;
|
||||
min-width: 100px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* =========================================================== */
|
||||
@@ -397,17 +471,6 @@ label:hover { color: var(--c-primary); }
|
||||
|
||||
.toolbar-button.purple-gradient:hover { box-shadow: var(--shadow-purple-4); }
|
||||
|
||||
/* =========================================================== */
|
||||
/* 分隔线样式 */
|
||||
/* =========================================================== */
|
||||
|
||||
.toolbar-separator {
|
||||
width: 1px;
|
||||
height: 24px;
|
||||
background: var(--c-border);
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
/* =========================================================== */
|
||||
/* Doc Modal 样式 */
|
||||
/* =========================================================== */
|
||||
@@ -485,11 +548,11 @@ label:hover { color: var(--c-primary); }
|
||||
"content content content content content content"
|
||||
"content content content content content content"
|
||||
"pagination pagination pagination slice slice slice";
|
||||
gap: 12px;
|
||||
gap: 5px;
|
||||
width: 100%;
|
||||
background: var(--grad-xhs-bg);
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
padding: 5px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
409
styles.css.bk
409
styles.css.bk
@@ -70,11 +70,10 @@
|
||||
.wechat-select:hover { border-color: var(--c-primary); }
|
||||
.platform-select:focus,
|
||||
.wechat-select:focus { outline: none; border-color: var(--c-primary); }
|
||||
|
||||
.note-preview {
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr;
|
||||
grid-template-columns: 1fr;
|
||||
display: grid;
|
||||
min-height: 100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -85,22 +84,14 @@
|
||||
.wechat-preview-container:not([style*="display: none"]),
|
||||
.xiaohongshu-preview-container:not([style*="display: none"]) {
|
||||
flex: 1;
|
||||
display: grid !important;
|
||||
grid-template-rows: auto 1fr;
|
||||
display: flex !important;
|
||||
min-height: 0; /* 允许内部滚动区域正确计算高度 */
|
||||
}
|
||||
|
||||
.render-div {
|
||||
overflow-y: auto;
|
||||
padding: 10px;
|
||||
-webkit-user-select: text;
|
||||
user-select: text;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
/* 文章包裹:模拟公众号编辑器阅读宽度 */
|
||||
.wechat-article-wrapper {
|
||||
max-width: 720px;
|
||||
width: 100%;
|
||||
max-width: clamp(360px, 80vw, 760px);
|
||||
margin: 0 auto;
|
||||
padding: 12px 18px 80px 18px; /* 底部留白方便滚动到底部操作 */
|
||||
box-sizing: border-box;
|
||||
@@ -111,19 +102,6 @@
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.preview-toolbar {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, max-content));
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
min-height: auto;
|
||||
padding: 8px 12px;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
background: var(--grad-toolbar);
|
||||
box-shadow: var(--shadow-overlay);
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
margin-right: 10px;
|
||||
padding: 6px 14px;
|
||||
@@ -313,23 +291,6 @@ label:hover { color: var(--c-primary); }
|
||||
/* Toolbar 行样式 */
|
||||
/* =========================================================== */
|
||||
|
||||
.toolbar-line {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 8px 12px;
|
||||
background: white;
|
||||
border-radius: 6px;
|
||||
margin: 8px 10px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.toolbar-line.flex-wrap {
|
||||
grid-auto-flow: row;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, max-content));
|
||||
}
|
||||
|
||||
.platform-selector-line {
|
||||
background: linear-gradient(135deg, #fff3e0 0%, #ffffff 100%) !important;
|
||||
border-left: 4px solid var(--c-primary);
|
||||
@@ -338,7 +299,7 @@ label:hover { color: var(--c-primary); }
|
||||
/* 平台选择容器:单层 Grid 排列 */
|
||||
.platform-chooser-container.platform-chooser-grid {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
grid-template-columns: auto minmax(160px, 1fr) auto auto;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 8px 12px;
|
||||
@@ -348,6 +309,16 @@ label:hover { color: var(--c-primary); }
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.platform-chooser-container .toolbar-button {
|
||||
justify-self: start;
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.platform-chooser-container.platform-chooser-grid {
|
||||
grid-template-columns: repeat(auto-fit, minmax(140px, max-content));
|
||||
}
|
||||
}
|
||||
|
||||
/* =========================================================== */
|
||||
/* 平台选择器样式 */
|
||||
/* =========================================================== */
|
||||
@@ -358,13 +329,119 @@ label:hover { color: var(--c-primary); }
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* =========================================================== */
|
||||
/* 微信公众号预览布局 */
|
||||
/* =========================================================== */
|
||||
|
||||
.wechat-preview-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
padding: 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.wechat-board {
|
||||
flex: 1;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, minmax(0, 1fr));
|
||||
grid-template-rows: auto auto auto minmax(0, 1fr);
|
||||
grid-template-areas:
|
||||
"account-label account-select account-select account-select account-backend account-export"
|
||||
"cover-label cover-default cover-upload cover-input cover-input cover-input"
|
||||
"style-label style-select highlight-label highlight-select highlight-select highlight-select"
|
||||
"content content content content content content";
|
||||
gap: 12px;
|
||||
background: var(--grad-toolbar);
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.wechat-cell {
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
padding: 12px 16px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.wechat-cell[data-area="account-label"] { grid-area: account-label; white-space: nowrap; justify-content: flex-start; }
|
||||
.wechat-cell[data-area="account-select"] { grid-area: account-select; }
|
||||
.wechat-cell[data-area="account-backend"] { grid-area: account-backend; justify-content: flex-end; }
|
||||
.wechat-cell[data-area="account-export"] { grid-area: account-export; justify-content: flex-end; }
|
||||
|
||||
.wechat-cell[data-area="account-select"] .wechat-select {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wechat-cell[data-area="account-backend"] .wechat-action-button,
|
||||
.wechat-cell[data-area="account-export"] .wechat-action-button {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.wechat-cell[data-area="cover-label"] { grid-area: cover-label; white-space: nowrap; justify-content: flex-start; }
|
||||
.wechat-cell[data-area="cover-default"] { grid-area: cover-default; gap: 8px; }
|
||||
.wechat-cell[data-area="cover-upload"] { grid-area: cover-upload; gap: 8px; }
|
||||
.wechat-cell[data-area="cover-input"] { grid-area: cover-input; }
|
||||
|
||||
.wechat-cell[data-area="cover-default"] label,
|
||||
.wechat-cell[data-area="cover-upload"] label {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.wechat-cell[data-area="cover-input"] .upload-input {
|
||||
margin-left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wechat-cell[data-area="style-label"] { grid-area: style-label; white-space: nowrap; justify-content: flex-start; }
|
||||
.wechat-cell[data-area="style-select"] { grid-area: style-select; width: 100%; }
|
||||
.wechat-cell[data-area="highlight-label"] { grid-area: highlight-label; white-space: nowrap; justify-content: flex-start; }
|
||||
.wechat-cell[data-area="highlight-select"] { grid-area: highlight-select; width: 100%; }
|
||||
|
||||
.wechat-cell[data-area="style-select"] .style-select,
|
||||
.wechat-cell[data-area="style-select"] .wechat-style-select,
|
||||
.wechat-cell[data-area="highlight-select"] .style-select,
|
||||
.wechat-cell[data-area="highlight-select"] .wechat-style-select {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.wechat-cell[data-area="content"] {
|
||||
grid-area: content;
|
||||
overflow-y: auto;
|
||||
padding: 10px;
|
||||
-webkit-user-select: text;
|
||||
user-select: text;
|
||||
min-height: 0;
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
display: block;
|
||||
}
|
||||
|
||||
.wechat-cell-placeholder {
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.wechat-cell-placeholder .toolbar-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* =========================================================== */
|
||||
/* 微信公众号选择器样式 */
|
||||
/* =========================================================== */
|
||||
|
||||
.wechat-select {
|
||||
padding: 6px 12px;
|
||||
min-width: 200px;
|
||||
min-width: 100px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* =========================================================== */
|
||||
@@ -388,17 +465,6 @@ label:hover { color: var(--c-primary); }
|
||||
|
||||
.toolbar-button.purple-gradient:hover { box-shadow: var(--shadow-purple-4); }
|
||||
|
||||
/* =========================================================== */
|
||||
/* 分隔线样式 */
|
||||
/* =========================================================== */
|
||||
|
||||
.toolbar-separator {
|
||||
width: 1px;
|
||||
height: 24px;
|
||||
background: var(--c-border);
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
/* =========================================================== */
|
||||
/* Doc Modal 样式 */
|
||||
/* =========================================================== */
|
||||
@@ -461,38 +527,138 @@ label:hover { color: var(--c-primary); }
|
||||
.xiaohongshu-preview-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
padding: 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.xhs-preview-container:not([style*="display: none"]) {
|
||||
display: grid !important;
|
||||
grid-template-rows: auto 1fr auto;
|
||||
height: 100%;
|
||||
.xhs-board {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, minmax(0, 1fr));
|
||||
grid-template-rows: auto auto auto 1fr auto;
|
||||
grid-template-areas:
|
||||
"template template preview preview font font"
|
||||
"content content content content content content"
|
||||
"content content content content content content"
|
||||
"content content content content content content"
|
||||
"pagination pagination pagination slice slice slice";
|
||||
gap: 5px;
|
||||
width: 100%;
|
||||
background: var(--grad-xhs-bg);
|
||||
border-radius: 12px;
|
||||
padding: 5px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.xhs-page-container {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
display: grid;
|
||||
align-content: start;
|
||||
justify-content: center;
|
||||
padding: 0px;
|
||||
background: radial-gradient(ellipse at top, rgba(255,255,255,0.1) 0%, transparent 70%);
|
||||
min-height: 0; /* 允许子项正确收缩和滚动 */
|
||||
.xhs-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
padding: 10px 14px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.xhs-label {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: var(--c-text-muted);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.xhs-select {
|
||||
flex: 1 1 auto;
|
||||
padding: 6px 10px;
|
||||
border: 1px solid var(--c-border);
|
||||
border-radius: 6px;
|
||||
background: white;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
max-width: 100px;
|
||||
transition: border-color 0.2s ease;
|
||||
}
|
||||
|
||||
.xhs-select:hover { border-color: var(--c-primary); }
|
||||
|
||||
.xhs-select:focus {
|
||||
outline: none;
|
||||
border-color: var(--c-primary);
|
||||
box-shadow: 0 0 0 3px rgba(30, 136, 229, 0.1);
|
||||
}
|
||||
|
||||
.font-size-group {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 2px;
|
||||
border: 1px solid var(--c-border);
|
||||
border-radius: 6px;
|
||||
background: #f7f9fb;
|
||||
}
|
||||
|
||||
.font-size-btn {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
color: #5f6368;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.font-size-btn:hover { background: #eaf1fe; }
|
||||
|
||||
.font-size-input {
|
||||
width: 35px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
text-align: center;
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.font-size-input:focus { outline: none; }
|
||||
|
||||
.xhs-area-template { grid-area: template; }
|
||||
.xhs-area-preview { grid-area: preview; }
|
||||
.xhs-area-font {
|
||||
grid-area: font;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.xhs-area-pagination { grid-area: pagination; justify-content: center; gap: 16px; }
|
||||
.xhs-area-slice { grid-area: slice; justify-content: center; gap: 16px; }
|
||||
|
||||
.xhs-area-content {
|
||||
grid-area: content;
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 0;
|
||||
box-shadow: var(--shadow-sm);
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.xhs-page-container {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
background: radial-gradient(ellipse at top, rgba(255,255,255,0.1) 0%, transparent 70%);
|
||||
border-radius: 12px;
|
||||
min-height: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 小红书单页包裹器:为缩放后的页面预留正确的布局空间 */
|
||||
.xhs-page-wrapper {
|
||||
margin: 0px auto;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 小红书单页样式:实际尺寸 1080×1440,通过 scale 缩放到 540×720 */
|
||||
.xhs-page {
|
||||
/* 实际尺寸与缩放由代码在运行时设置 */
|
||||
transform-origin: top left;
|
||||
background: white;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
||||
border-radius: 8px;
|
||||
@@ -503,87 +669,10 @@ label:hover { color: var(--c-primary); }
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.xhs-top-toolbar {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(140px, max-content));
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 8px 12px;
|
||||
background: var(--grad-toolbar);
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
box-shadow: var(--shadow-overlay);
|
||||
}
|
||||
|
||||
.toolbar-label {
|
||||
font-size: 11px;
|
||||
color: var(--c-text-muted);
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.xhs-select {
|
||||
padding: 4px 8px;
|
||||
border: 1px solid var(--c-border);
|
||||
border-radius: 4px;
|
||||
background: white;
|
||||
font-size: 11px;
|
||||
cursor: pointer;
|
||||
transition: border-color 0.2s ease;
|
||||
}
|
||||
|
||||
.xhs-select:hover {
|
||||
border-color: var(--c-primary);
|
||||
}
|
||||
|
||||
.xhs-select:focus {
|
||||
outline: none;
|
||||
border-color: var(--c-primary);
|
||||
}
|
||||
|
||||
.font-size-group {
|
||||
.xhs-pagination {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
background: white;
|
||||
border: 1px solid var(--c-border);
|
||||
border-radius: 4px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.font-size-btn {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
color: #5f6368;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.font-size-btn:hover {
|
||||
background: #f1f3f4;
|
||||
}
|
||||
|
||||
.font-size-display {
|
||||
min-width: 24px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
color: #202124;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.xhs-page-navigation {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
padding: 12px;
|
||||
background: white;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
}
|
||||
|
||||
.xhs-nav-btn {
|
||||
@@ -605,7 +694,6 @@ label:hover { color: var(--c-primary); }
|
||||
border-color: var(--c-primary);
|
||||
}
|
||||
|
||||
/* 页码指示器:输入框 + 总页数标记 */
|
||||
.xhs-page-indicator {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
@@ -615,9 +703,8 @@ label:hover { color: var(--c-primary); }
|
||||
color: #202124;
|
||||
}
|
||||
|
||||
/* 可编辑页码输入框 */
|
||||
.xhs-page-number-input {
|
||||
width: 56px;
|
||||
width: 35px;
|
||||
padding: 4px 6px;
|
||||
text-align: center;
|
||||
border: 1px solid var(--c-border);
|
||||
@@ -635,24 +722,12 @@ label:hover { color: var(--c-primary); }
|
||||
box-shadow: 0 0 0 3px rgba(30, 136, 229, 0.15);
|
||||
}
|
||||
|
||||
/* 总页数显示(只读) */
|
||||
.xhs-page-number-total {
|
||||
font-size: 14px;
|
||||
color: #5f6368;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.xhs-bottom-toolbar {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
padding: 12px 16px;
|
||||
background: var(--grad-toolbar-bottom);
|
||||
border-top: 1px solid #e8eaed;
|
||||
box-shadow: 0 -2px 4px rgba(0,0,0,0.04);
|
||||
}
|
||||
|
||||
.xhs-slice-btn {
|
||||
padding: 8px 20px;
|
||||
background: var(--grad-primary);
|
||||
|
||||
Reference in New Issue
Block a user