diff --git a/release.md b/release.md index 8fe7805..49d7688 100644 --- a/release.md +++ b/release.md @@ -61,4 +61,6 @@ 现在分页依据真实渲染高度,预览窗口内不会再丢失底部内容。建议在小红书预览里多翻几页、调整字号后重新分页验证结果。 +## v1.3.9 +重构xhs和wechat布局,统一使用grid,便于维护。 diff --git a/src/wechat/wechat-preview.ts b/src/wechat/wechat-preview.ts index c9df883..f8d2147 100644 --- a/src/wechat/wechat-preview.ts +++ b/src/wechat/wechat-preview.ts @@ -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; diff --git a/styles.css b/styles.css index a72ce49..6a22be2 100644 --- a/styles.css +++ b/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; } diff --git a/styles.css.bk b/styles.css.bk index 2a29bdd..ba1c681 100644 --- a/styles.css.bk +++ b/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);