From 6f51916b505cd2bcf1f8103bdea32346e06fe563 Mon Sep 17 00:00:00 2001 From: douboer Date: Thu, 9 Oct 2025 12:39:24 +0800 Subject: [PATCH] update at 2025-10-09 12:39:24 --- BUGFIX_ASYNC_LOADING_ISSUE.md | 0 DEBUG_LOADING_ISSUE.md | 0 LICENSE | 2 +- TESTING_GUIDE.md | 0 build.sh | 21 +- .../ARCHITECTURE_COMPARISON.md | 0 .../ARCHITECTURE_QUICK_REFERENCE.md | 0 .../ARCHITECTURE_REFACTORING_COMPLETE.md | 0 .../BUGFIX_LOADING_AND_STYLE_ISSUE.md | 0 CHANGELOG.md => docs/CHANGELOG.md | 0 .../PLATFORM_REFACTORING_SUMMARY.md | 0 .../README_PLATFORM_SELECTOR_DONE.md | 0 .../README_XIAOHONGSHU_LAYOUT_DONE.md | 0 .../SLICE_IMAGE_GUIDE.md | 0 .../XIAOHONGSHU_COMPACT_LAYOUT.md | 0 .../XIAOHONGSHU_FEATURE_SUMMARY.md | 0 .../XIAOHONGSHU_KEEP_PLATFORM_SELECTOR.md | 0 .../XIAOHONGSHU_LAYOUT_CHANGE_LOG.md | 0 .../XIAOHONGSHU_PREVIEW_GUIDE.md | 0 .../XIAOHONGSHU_STYLE_OPTIMIZATION.md | 0 .../XIAOHONGSHU_UI_LAYOUT.md | 0 architecture.md => docs/architecture.md | 0 .../create_milestone.md | 0 detaildesign.md => docs/detaildesign.md | 0 diagrams.md => docs/diagrams.md | 0 image-pipeline.md => docs/image-pipeline.md | 0 mp_todolist.md => docs/mp_todolist.md | 0 .../render-service-blueprint.md | 0 xhs_todolist.md => docs/xhs_todolist.md | 0 xhspublisher.md => docs/xhspublisher.md | 0 .../xiaohongshu-design.md | 0 .../xiaohongshu-summary.md | 0 {src => docs}/xiaohongshu/automation-notes.md | 0 .../xiaohongshu/completion-summary.md | 0 {src => docs}/xiaohongshu/debug-guide.md | 0 images/xhs/note2mdtest_3.png | Bin 38087 -> 37548 bytes manifest.json | 10 +- src/platform-chooser.ts | 11 +- src/preview-manager.ts | 6 +- src/settings.ts | 11 +- src/wechat/wechat-preview.ts | 59 ++- src/xiaohongshu/xhs-preview.ts | 84 +++++ styles.css | 349 +++++++++--------- todolist.md | 5 +- 44 files changed, 332 insertions(+), 226 deletions(-) delete mode 100644 BUGFIX_ASYNC_LOADING_ISSUE.md delete mode 100644 DEBUG_LOADING_ISSUE.md delete mode 100644 TESTING_GUIDE.md rename ARCHITECTURE_COMPARISON.md => docs/ARCHITECTURE_COMPARISON.md (100%) rename ARCHITECTURE_QUICK_REFERENCE.md => docs/ARCHITECTURE_QUICK_REFERENCE.md (100%) rename ARCHITECTURE_REFACTORING_COMPLETE.md => docs/ARCHITECTURE_REFACTORING_COMPLETE.md (100%) rename BUGFIX_LOADING_AND_STYLE_ISSUE.md => docs/BUGFIX_LOADING_AND_STYLE_ISSUE.md (100%) rename CHANGELOG.md => docs/CHANGELOG.md (100%) rename PLATFORM_REFACTORING_SUMMARY.md => docs/PLATFORM_REFACTORING_SUMMARY.md (100%) rename README_PLATFORM_SELECTOR_DONE.md => docs/README_PLATFORM_SELECTOR_DONE.md (100%) rename README_XIAOHONGSHU_LAYOUT_DONE.md => docs/README_XIAOHONGSHU_LAYOUT_DONE.md (100%) rename SLICE_IMAGE_GUIDE.md => docs/SLICE_IMAGE_GUIDE.md (100%) rename XIAOHONGSHU_COMPACT_LAYOUT.md => docs/XIAOHONGSHU_COMPACT_LAYOUT.md (100%) rename XIAOHONGSHU_FEATURE_SUMMARY.md => docs/XIAOHONGSHU_FEATURE_SUMMARY.md (100%) rename XIAOHONGSHU_KEEP_PLATFORM_SELECTOR.md => docs/XIAOHONGSHU_KEEP_PLATFORM_SELECTOR.md (100%) rename XIAOHONGSHU_LAYOUT_CHANGE_LOG.md => docs/XIAOHONGSHU_LAYOUT_CHANGE_LOG.md (100%) rename XIAOHONGSHU_PREVIEW_GUIDE.md => docs/XIAOHONGSHU_PREVIEW_GUIDE.md (100%) rename XIAOHONGSHU_STYLE_OPTIMIZATION.md => docs/XIAOHONGSHU_STYLE_OPTIMIZATION.md (100%) rename XIAOHONGSHU_UI_LAYOUT.md => docs/XIAOHONGSHU_UI_LAYOUT.md (100%) rename architecture.md => docs/architecture.md (100%) rename create_milestone.md => docs/create_milestone.md (100%) rename detaildesign.md => docs/detaildesign.md (100%) rename diagrams.md => docs/diagrams.md (100%) rename image-pipeline.md => docs/image-pipeline.md (100%) rename mp_todolist.md => docs/mp_todolist.md (100%) rename render-service-blueprint.md => docs/render-service-blueprint.md (100%) rename xhs_todolist.md => docs/xhs_todolist.md (100%) rename xhspublisher.md => docs/xhspublisher.md (100%) rename xiaohongshu-design.md => docs/xiaohongshu-design.md (100%) rename xiaohongshu-summary.md => docs/xiaohongshu-summary.md (100%) rename {src => docs}/xiaohongshu/automation-notes.md (100%) rename {src => docs}/xiaohongshu/completion-summary.md (100%) rename {src => docs}/xiaohongshu/debug-guide.md (100%) diff --git a/BUGFIX_ASYNC_LOADING_ISSUE.md b/BUGFIX_ASYNC_LOADING_ISSUE.md deleted file mode 100644 index e69de29..0000000 diff --git a/DEBUG_LOADING_ISSUE.md b/DEBUG_LOADING_ISSUE.md deleted file mode 100644 index e69de29..0000000 diff --git a/LICENSE b/LICENSE index db4b010..9a406e9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2024 sunbooshi +Copyright (c) 2025 Gavin Chan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/TESTING_GUIDE.md b/TESTING_GUIDE.md deleted file mode 100644 index e69de29..0000000 diff --git a/build.sh b/build.sh index cc7eb02..dea2005 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,15 @@ set -e # 出错立即退出 # 1. 构建 -npm run build +echo "🏗️ 开始构建..." +if npm run build; then + echo "✅ 构建成功" + echo +else + echo "❌ 构建失败,脚本终止" + echo + exit 1 +fi # 2. 目标目录 PLUGIN_DIR=~/myweb/.obsidian/plugins/note-to-mp @@ -16,12 +24,12 @@ for FILE in "${FILES[@]}"; do if [ -f "$TARGET" ]; then mkdir -p "$(dirname "$BACKUP")" cp -f "$TARGET" "$BACKUP" - echo "已备份 $TARGET -> $BACKUP" + echo "💾 已备份 $TARGET -> $BACKUP" fi if [ -f "$FILE" ]; then cp -f "$FILE" "$TARGET" - echo "已更新 $TARGET" + echo "📂 已更新 $TARGET" else echo "⚠️ 源文件 $FILE 不存在,跳过" fi @@ -31,7 +39,12 @@ done if [ -d "assets" ]; then mkdir -p "$PLUGIN_DIR/assets" rsync -a --delete assets/ "$PLUGIN_DIR/assets/" >/dev/null - echo "已同步 assets -> $PLUGIN_DIR/assets/" + echo "🎨 已同步 assets -> $PLUGIN_DIR/assets/" + echo else echo "⚠️ 源目录 assets 不存在,跳过" + echo fi + +echo "✅ 部署完成!" +echo diff --git a/ARCHITECTURE_COMPARISON.md b/docs/ARCHITECTURE_COMPARISON.md similarity index 100% rename from ARCHITECTURE_COMPARISON.md rename to docs/ARCHITECTURE_COMPARISON.md diff --git a/ARCHITECTURE_QUICK_REFERENCE.md b/docs/ARCHITECTURE_QUICK_REFERENCE.md similarity index 100% rename from ARCHITECTURE_QUICK_REFERENCE.md rename to docs/ARCHITECTURE_QUICK_REFERENCE.md diff --git a/ARCHITECTURE_REFACTORING_COMPLETE.md b/docs/ARCHITECTURE_REFACTORING_COMPLETE.md similarity index 100% rename from ARCHITECTURE_REFACTORING_COMPLETE.md rename to docs/ARCHITECTURE_REFACTORING_COMPLETE.md diff --git a/BUGFIX_LOADING_AND_STYLE_ISSUE.md b/docs/BUGFIX_LOADING_AND_STYLE_ISSUE.md similarity index 100% rename from BUGFIX_LOADING_AND_STYLE_ISSUE.md rename to docs/BUGFIX_LOADING_AND_STYLE_ISSUE.md diff --git a/CHANGELOG.md b/docs/CHANGELOG.md similarity index 100% rename from CHANGELOG.md rename to docs/CHANGELOG.md diff --git a/PLATFORM_REFACTORING_SUMMARY.md b/docs/PLATFORM_REFACTORING_SUMMARY.md similarity index 100% rename from PLATFORM_REFACTORING_SUMMARY.md rename to docs/PLATFORM_REFACTORING_SUMMARY.md diff --git a/README_PLATFORM_SELECTOR_DONE.md b/docs/README_PLATFORM_SELECTOR_DONE.md similarity index 100% rename from README_PLATFORM_SELECTOR_DONE.md rename to docs/README_PLATFORM_SELECTOR_DONE.md diff --git a/README_XIAOHONGSHU_LAYOUT_DONE.md b/docs/README_XIAOHONGSHU_LAYOUT_DONE.md similarity index 100% rename from README_XIAOHONGSHU_LAYOUT_DONE.md rename to docs/README_XIAOHONGSHU_LAYOUT_DONE.md diff --git a/SLICE_IMAGE_GUIDE.md b/docs/SLICE_IMAGE_GUIDE.md similarity index 100% rename from SLICE_IMAGE_GUIDE.md rename to docs/SLICE_IMAGE_GUIDE.md diff --git a/XIAOHONGSHU_COMPACT_LAYOUT.md b/docs/XIAOHONGSHU_COMPACT_LAYOUT.md similarity index 100% rename from XIAOHONGSHU_COMPACT_LAYOUT.md rename to docs/XIAOHONGSHU_COMPACT_LAYOUT.md diff --git a/XIAOHONGSHU_FEATURE_SUMMARY.md b/docs/XIAOHONGSHU_FEATURE_SUMMARY.md similarity index 100% rename from XIAOHONGSHU_FEATURE_SUMMARY.md rename to docs/XIAOHONGSHU_FEATURE_SUMMARY.md diff --git a/XIAOHONGSHU_KEEP_PLATFORM_SELECTOR.md b/docs/XIAOHONGSHU_KEEP_PLATFORM_SELECTOR.md similarity index 100% rename from XIAOHONGSHU_KEEP_PLATFORM_SELECTOR.md rename to docs/XIAOHONGSHU_KEEP_PLATFORM_SELECTOR.md diff --git a/XIAOHONGSHU_LAYOUT_CHANGE_LOG.md b/docs/XIAOHONGSHU_LAYOUT_CHANGE_LOG.md similarity index 100% rename from XIAOHONGSHU_LAYOUT_CHANGE_LOG.md rename to docs/XIAOHONGSHU_LAYOUT_CHANGE_LOG.md diff --git a/XIAOHONGSHU_PREVIEW_GUIDE.md b/docs/XIAOHONGSHU_PREVIEW_GUIDE.md similarity index 100% rename from XIAOHONGSHU_PREVIEW_GUIDE.md rename to docs/XIAOHONGSHU_PREVIEW_GUIDE.md diff --git a/XIAOHONGSHU_STYLE_OPTIMIZATION.md b/docs/XIAOHONGSHU_STYLE_OPTIMIZATION.md similarity index 100% rename from XIAOHONGSHU_STYLE_OPTIMIZATION.md rename to docs/XIAOHONGSHU_STYLE_OPTIMIZATION.md diff --git a/XIAOHONGSHU_UI_LAYOUT.md b/docs/XIAOHONGSHU_UI_LAYOUT.md similarity index 100% rename from XIAOHONGSHU_UI_LAYOUT.md rename to docs/XIAOHONGSHU_UI_LAYOUT.md diff --git a/architecture.md b/docs/architecture.md similarity index 100% rename from architecture.md rename to docs/architecture.md diff --git a/create_milestone.md b/docs/create_milestone.md similarity index 100% rename from create_milestone.md rename to docs/create_milestone.md diff --git a/detaildesign.md b/docs/detaildesign.md similarity index 100% rename from detaildesign.md rename to docs/detaildesign.md diff --git a/diagrams.md b/docs/diagrams.md similarity index 100% rename from diagrams.md rename to docs/diagrams.md diff --git a/image-pipeline.md b/docs/image-pipeline.md similarity index 100% rename from image-pipeline.md rename to docs/image-pipeline.md diff --git a/mp_todolist.md b/docs/mp_todolist.md similarity index 100% rename from mp_todolist.md rename to docs/mp_todolist.md diff --git a/render-service-blueprint.md b/docs/render-service-blueprint.md similarity index 100% rename from render-service-blueprint.md rename to docs/render-service-blueprint.md diff --git a/xhs_todolist.md b/docs/xhs_todolist.md similarity index 100% rename from xhs_todolist.md rename to docs/xhs_todolist.md diff --git a/xhspublisher.md b/docs/xhspublisher.md similarity index 100% rename from xhspublisher.md rename to docs/xhspublisher.md diff --git a/xiaohongshu-design.md b/docs/xiaohongshu-design.md similarity index 100% rename from xiaohongshu-design.md rename to docs/xiaohongshu-design.md diff --git a/xiaohongshu-summary.md b/docs/xiaohongshu-summary.md similarity index 100% rename from xiaohongshu-summary.md rename to docs/xiaohongshu-summary.md diff --git a/src/xiaohongshu/automation-notes.md b/docs/xiaohongshu/automation-notes.md similarity index 100% rename from src/xiaohongshu/automation-notes.md rename to docs/xiaohongshu/automation-notes.md diff --git a/src/xiaohongshu/completion-summary.md b/docs/xiaohongshu/completion-summary.md similarity index 100% rename from src/xiaohongshu/completion-summary.md rename to docs/xiaohongshu/completion-summary.md diff --git a/src/xiaohongshu/debug-guide.md b/docs/xiaohongshu/debug-guide.md similarity index 100% rename from src/xiaohongshu/debug-guide.md rename to docs/xiaohongshu/debug-guide.md diff --git a/images/xhs/note2mdtest_3.png b/images/xhs/note2mdtest_3.png index 37f1a900cfc3d89a9297182ae3da3a791464edb0..fac806bfbef7e8844a65508b3085747e47384da7 100644 GIT binary patch literal 37548 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 Ve!m9)BnA9CWNu}a^V8|;{{z=jcW(dy literal 38087 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 diff --git a/manifest.json b/manifest.json index e05f008..f8d150c 100644 --- a/manifest.json +++ b/manifest.json @@ -1,10 +1,10 @@ { "id": "note-to-mp", - "name": "NoteToMP", - "version": "1.3.0", + "name": "NoteToAny", + "version": "1.3.4", "minAppVersion": "1.4.5", - "description": "Send notes to WeChat MP drafts, or copy notes to WeChat MP editor, perfect preservation of note styles, support code highlighting, line numbers in code, and support local image uploads.", - "author": "Sun Booshi", - "authorUrl": "https://sunboshi.tech", + "description": "xiaohongshu/mp publisher ", + "author": "Gavin chan", + "authorUrl": "https://biboer.cn", "isDesktopOnly": false } diff --git a/src/platform-chooser.ts b/src/platform-chooser.ts index 64036cd..65de878 100644 --- a/src/platform-chooser.ts +++ b/src/platform-chooser.ts @@ -53,7 +53,7 @@ export class PlatformChooser { constructor(container: HTMLElement, options: PlatformChooserOptions = {}) { this.container = container; - this.currentPlatform = options.defaultPlatform || 'wechat'; + this.currentPlatform = options.defaultPlatform || 'xiaohongshu'; if (options.onPlatformChange) { this.onChange = (platform) => { options.onPlatformChange!(platform); @@ -72,15 +72,16 @@ export class PlatformChooser { * 渲染平台选择器 UI */ render(): void { - // 创建平台选择行 - const lineDiv = this.container.createDiv({ cls: 'toolbar-line platform-selector-line' }); + // 将容器作为单层 Grid 行使用 + this.container.addClass('platform-selector-line'); + this.container.addClass('platform-chooser-grid'); // 创建标签 - const platformLabel = lineDiv.createDiv({ cls: 'style-label' }); + const platformLabel = this.container.createDiv({ cls: 'style-label' }); platformLabel.innerText = '发布平台'; // 创建选择器 - const platformSelect = lineDiv.createEl('select', { cls: 'platform-select' }); + const platformSelect = this.container.createEl('select', { cls: 'platform-select' }); this.selectElement = platformSelect; // 添加平台选项 diff --git a/src/preview-manager.ts b/src/preview-manager.ts index 79998c9..65becf4 100644 --- a/src/preview-manager.ts +++ b/src/preview-manager.ts @@ -37,7 +37,7 @@ export class PreviewManager { private xhsContainer: HTMLDivElement | null = null; // 状态 - private currentPlatform: PlatformType = 'wechat'; + private currentPlatform: PlatformType = 'xiaohongshu'; private currentFile: TFile | null = null; constructor(container: HTMLElement, app: App, render: ArticleRender) { @@ -68,8 +68,8 @@ export class PreviewManager { // 3. 创建并构建小红书预览 this.createXiaohongshuPreview(); - // 4. 初始显示微信平台 - await this.switchPlatform('wechat'); + // 4. 初始显示小红书平台 + await this.switchPlatform('xiaohongshu'); console.log('[PreviewManager] 界面构建完成'); } diff --git a/src/settings.ts b/src/settings.ts index dafc062..ae1c2ca 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -51,6 +51,7 @@ export class NMPSettings { sliceImageSavePath: string; // 切图保存路径 sliceImageWidth: number; // 切图宽度(像素) sliceImageAspectRatio: string; // 横竖比例,格式 "3:4" + xhsPreviewWidth: number; // 小红书预览宽度(像素) private static instance: NMPSettings; @@ -100,6 +101,7 @@ export class NMPSettings { this.sliceImageSavePath = '/Users/gavin/note2mp/images/xhs'; this.sliceImageWidth = 1080; this.sliceImageAspectRatio = '3:4'; + this.xhsPreviewWidth = 540; } resetStyelAndHighlight() { @@ -136,7 +138,8 @@ export class NMPSettings { batchPublishPresets = [], sliceImageSavePath, sliceImageWidth, - sliceImageAspectRatio + sliceImageAspectRatio, + xhsPreviewWidth } = data; const settings = NMPSettings.getInstance(); @@ -166,6 +169,9 @@ export class NMPSettings { if (sliceImageSavePath) settings.sliceImageSavePath = sliceImageSavePath; if (sliceImageWidth !== undefined && Number.isFinite(sliceImageWidth)) settings.sliceImageWidth = Math.max(100, parseInt(sliceImageWidth)); if (sliceImageAspectRatio) settings.sliceImageAspectRatio = sliceImageAspectRatio; + if (xhsPreviewWidth !== undefined && Number.isFinite(xhsPreviewWidth)) { + settings.xhsPreviewWidth = Math.max(100, parseInt(xhsPreviewWidth)); + } settings.getExpiredDate(); settings.isLoaded = true; @@ -200,6 +206,7 @@ export class NMPSettings { 'sliceImageSavePath': settings.sliceImageSavePath, 'sliceImageWidth': settings.sliceImageWidth, 'sliceImageAspectRatio': settings.sliceImageAspectRatio, + 'xhsPreviewWidth': settings.xhsPreviewWidth, } } @@ -221,4 +228,4 @@ export class NMPSettings { if (this.expireat == null) return false; return this.expireat > new Date(); } -} \ No newline at end of file +} diff --git a/src/wechat/wechat-preview.ts b/src/wechat/wechat-preview.ts index 9fd7be1..a58d3e1 100644 --- a/src/wechat/wechat-preview.ts +++ b/src/wechat/wechat-preview.ts @@ -93,25 +93,23 @@ export class WechatPreview { * 构建工具栏 */ private buildToolbar(parent: HTMLDivElement): void { - let lineDiv; + // 单层 Grid:所有控件直接挂到 parent(.preview-toolbar) // 公众号选择 if (this.settings.wxInfo.length > 1 || Platform.isDesktop) { - lineDiv = parent.createDiv({ cls: 'toolbar-line' }); - - const wxLabel = lineDiv.createDiv({ cls: 'style-label' }); + const wxLabel = parent.createDiv({ cls: 'style-label' }); wxLabel.innerText = '公众号'; - - const wxSelect = lineDiv.createEl('select', { cls: 'wechat-select' }); + + const wxSelect = parent.createEl('select', { cls: 'wechat-select' }); 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]; @@ -125,8 +123,8 @@ export class WechatPreview { this.wechatSelect = wxSelect; if (Platform.isDesktop) { - const separator = lineDiv.createDiv({ cls: 'toolbar-separator' }); - const openBtn = lineDiv.createEl('button', { text: '🌐 去公众号后台', cls: 'toolbar-button purple-gradient' }); + //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'); @@ -135,21 +133,15 @@ export class WechatPreview { } } - // 操作按钮行 - lineDiv = parent.createDiv({ cls: 'toolbar-line flex-wrap' }); - - const refreshBtn = lineDiv.createEl('button', { text: '🔄 刷新', cls: 'toolbar-button purple-gradient' }); - refreshBtn.onclick = async () => { - if (this.onRefreshCallback) { - await this.onRefreshCallback(); - } - }; + // 操作按钮(直接平铺在 Grid 中) + const refreshBtn = parent.createEl('button', { text: '🔄 刷新', cls: 'toolbar-button purple-gradient' }); + refreshBtn.onclick = async () => { if (this.onRefreshCallback) await this.onRefreshCallback(); }; - const postBtn = lineDiv.createEl('button', { text: '📝 发布', cls: 'toolbar-button' }); + const postBtn = parent.createEl('button', { text: '📝 发布', cls: 'toolbar-button' }); postBtn.onclick = async () => await this.postArticle(); if (Platform.isDesktop && this.settings.isAuthKeyVaild()) { - const htmlBtn = lineDiv.createEl('button', { text: '💾 导出HTML', cls: 'toolbar-button' }); + const htmlBtn = parent.createEl('button', { text: '💾 导出HTML', cls: 'toolbar-button' }); htmlBtn.onclick = async () => await this.exportHTML(); } @@ -166,11 +158,10 @@ export class WechatPreview { * 构建封面选择器 */ private buildCoverSelector(parent: HTMLDivElement): void { - const lineDiv = parent.createDiv({ cls: 'toolbar-line' }); - const coverTitle = lineDiv.createDiv({ cls: 'style-label' }); + const coverTitle = parent.createDiv({ cls: 'style-label' }); coverTitle.innerText = '封面'; - this.useDefaultCover = lineDiv.createEl('input', { cls: 'input-style' }); + this.useDefaultCover = parent.createEl('input', { cls: 'input-style' }); this.useDefaultCover.setAttr('type', 'radio'); this.useDefaultCover.setAttr('name', 'cover'); this.useDefaultCover.setAttr('value', 'default'); @@ -182,11 +173,11 @@ export class WechatPreview { } }; - const defaultLabel = lineDiv.createEl('label'); + const defaultLabel = parent.createEl('label'); defaultLabel.innerText = '默认'; defaultLabel.setAttr('for', 'default-cover'); - this.useLocalCover = lineDiv.createEl('input', { cls: 'input-style' }); + this.useLocalCover = parent.createEl('input', { cls: 'input-style' }); this.useLocalCover.setAttr('type', 'radio'); this.useLocalCover.setAttr('name', 'cover'); this.useLocalCover.setAttr('value', 'local'); @@ -198,11 +189,11 @@ export class WechatPreview { } }; - const localLabel = lineDiv.createEl('label'); + const localLabel = parent.createEl('label'); localLabel.setAttr('for', 'local-cover'); localLabel.innerText = '上传'; - this.coverEl = lineDiv.createEl('input', { cls: 'upload-input' }); + this.coverEl = parent.createEl('input', { cls: 'upload-input' }); this.coverEl.setAttr('type', 'file'); this.coverEl.setAttr('placeholder', '封面图片'); this.coverEl.setAttr('accept', '.png, .jpg, .jpeg'); @@ -214,12 +205,10 @@ export class WechatPreview { * 构建样式选择器 */ private buildStyleSelector(parent: HTMLDivElement): void { - const lineDiv = parent.createDiv({ cls: 'toolbar-line flex-wrap' }); - - const cssStyle = lineDiv.createDiv({ cls: 'style-label' }); + const cssStyle = parent.createDiv({ cls: 'style-label' }); cssStyle.innerText = '样式'; - const selectBtn = lineDiv.createEl('select', { cls: 'style-select' }); + const selectBtn = parent.createEl('select', { cls: 'style-select' }); selectBtn.onchange = async () => { this.currentTheme = selectBtn.value; this.render.updateStyle(selectBtn.value); @@ -233,12 +222,12 @@ export class WechatPreview { } this.themeSelect = selectBtn; - const separator = lineDiv.createDiv({ cls: 'toolbar-separator' }); + parent.createDiv({ cls: 'toolbar-separator' }); - const highlightStyle = lineDiv.createDiv({ cls: 'style-label' }); + const highlightStyle = parent.createDiv({ cls: 'style-label' }); highlightStyle.innerText = '代码高亮'; - const highlightStyleBtn = lineDiv.createEl('select', { cls: 'style-select' }); + const highlightStyleBtn = parent.createEl('select', { cls: 'style-select' }); highlightStyleBtn.onchange = async () => { this.currentHighlight = highlightStyleBtn.value; this.render.updateHighLight(highlightStyleBtn.value); diff --git a/src/xiaohongshu/xhs-preview.ts b/src/xiaohongshu/xhs-preview.ts index 9bc0c36..729839b 100644 --- a/src/xiaohongshu/xhs-preview.ts +++ b/src/xiaohongshu/xhs-preview.ts @@ -15,6 +15,9 @@ import AssetsManager from '../assets'; import { paginateArticle, renderPage, PageInfo } from './paginator'; import { sliceCurrentPage, sliceAllPages } from './slice'; +const XHS_PREVIEW_DEFAULT_WIDTH = 540; +const XHS_PREVIEW_WIDTH_OPTIONS = [1080, 720, 540, 360]; + /** * 小红书预览视图类 */ @@ -29,6 +32,7 @@ export class XiaohongshuPreview { topToolbar!: HTMLDivElement; templateSelect!: HTMLSelectElement; fontSizeInput!: HTMLInputElement; + previewWidthSelect!: HTMLSelectElement; pageContainer!: HTMLDivElement; bottomToolbar!: HTMLDivElement; @@ -110,6 +114,30 @@ export class XiaohongshuPreview { option.text = name; }); + const previewWidthLabel = this.topToolbar.createDiv({ cls: 'toolbar-label' }); + previewWidthLabel.innerText = '预览宽度'; + this.previewWidthSelect = this.topToolbar.createEl('select', { cls: 'xhs-select' }); + const currentPreviewWidth = this.settings.xhsPreviewWidth || XHS_PREVIEW_DEFAULT_WIDTH; + XHS_PREVIEW_WIDTH_OPTIONS.forEach(value => { + const option = this.previewWidthSelect.createEl('option'); + option.value = String(value); + option.text = `${value}px`; + }); + if (!XHS_PREVIEW_WIDTH_OPTIONS.includes(currentPreviewWidth)) { + const customOption = this.previewWidthSelect.createEl('option'); + customOption.value = String(currentPreviewWidth); + customOption.text = `${currentPreviewWidth}px`; + } + this.previewWidthSelect.value = String(currentPreviewWidth); + this.previewWidthSelect.onchange = async () => { + const value = parseInt(this.previewWidthSelect.value, 10); + if (Number.isFinite(value) && value > 0) { + await this.onPreviewWidthChanged(value); + } else { + this.previewWidthSelect.value = String(this.settings.xhsPreviewWidth || XHS_PREVIEW_DEFAULT_WIDTH); + } + }; + // 字号控制(可直接编辑) const fontSizeLabel = this.topToolbar.createDiv({ cls: 'toolbar-label' }); fontSizeLabel.innerText = '字号'; @@ -205,6 +233,7 @@ export class XiaohongshuPreview { if (this.currentThemeClass) classes.push('note-to-mp'); const pageElement = wrapper.createDiv({ cls: classes.join(' ') }); renderPage(pageElement, page.content, this.settings); + this.applyPreviewSizing(wrapper, pageElement); // 应用字体设置 this.applyFontSettings(pageElement); @@ -213,6 +242,49 @@ export class XiaohongshuPreview { this.pageNumberDisplay.innerText = `${this.currentPageIndex + 1}/${this.pages.length}`; } + /** + * 根据设置的宽度和横竖比应用预览尺寸与缩放 + */ + private applyPreviewSizing(wrapper: HTMLElement, pageElement: HTMLElement): void { + const configuredWidth = this.settings.sliceImageWidth || 1080; + const actualWidth = Math.max(1, configuredWidth); + const ratio = this.parseAspectRatio(this.settings.sliceImageAspectRatio); + const actualHeight = Math.round((actualWidth * ratio.height) / ratio.width); + const previewWidthSetting = this.settings.xhsPreviewWidth || XHS_PREVIEW_DEFAULT_WIDTH; + const previewWidth = Math.max(1, previewWidthSetting); + const scale = Math.max(previewWidth / actualWidth, 0.01); + const previewHeight = Math.max(1, Math.round(actualHeight * scale)); + + wrapper.style.width = `${previewWidth}px`; + wrapper.style.height = `${previewHeight}px`; + + pageElement.style.width = `${actualWidth}px`; + pageElement.style.height = `${actualHeight}px`; + pageElement.style.transform = `scale(${scale})`; + pageElement.style.position = 'absolute'; + pageElement.style.top = '0'; + pageElement.style.left = '0'; + } + + private async onPreviewWidthChanged(newWidth: number): Promise { + if (newWidth <= 0) return; + if (this.settings.xhsPreviewWidth === newWidth) return; + this.settings.xhsPreviewWidth = newWidth; + await this.persistSettings(); + this.renderCurrentPage(); + } + + /** + * 解析横竖比例字符串 + */ + private parseAspectRatio(ratio: string | undefined): { width: number; height: number } { + const parts = (ratio ?? '').split(':').map(part => parseFloat(part.trim())); + if (parts.length === 2 && isFinite(parts[0]) && isFinite(parts[1]) && parts[0] > 0 && parts[1] > 0) { + return { width: parts[0], height: parts[1] }; + } + return { width: 3, height: 4 }; + } + /** * 应用字体设置(仅字号,字体从主题读取) */ @@ -341,6 +413,17 @@ export class XiaohongshuPreview { } } + private async persistSettings(): Promise { + try { + const plugin = (this.app as any)?.plugins?.getPlugin?.('note-to-mp'); + if (plugin?.saveSettings) { + await plugin.saveSettings(); + } + } catch (error) { + console.warn('[XiaohongshuPreview] 保存设置失败', error); + } + } + /** * 显示小红书预览视图 */ @@ -365,6 +448,7 @@ export class XiaohongshuPreview { destroy(): void { this.topToolbar = null as any; this.templateSelect = null as any; + this.previewWidthSelect = null as any; this.fontSizeInput = null as any; this.pageContainer = null as any; this.bottomToolbar = null as any; diff --git a/styles.css b/styles.css index a4fc570..23af5bb 100644 --- a/styles.css +++ b/styles.css @@ -2,26 +2,94 @@ /* =========================================================== */ /* UI 样式 */ +/* 共用样式与去重 */ /* =========================================================== */ + +/* 主题变量统一常用色值/阴影/渐变 */ +:root { + --c-bg: #ffffff; + --c-border: #dadce0; + --c-text-muted: #5f6368; + --c-primary: #1e88e5; + --c-primary-dark: #1565c0; + --c-purple: #667eea; + --c-purple-dark: #764ba2; + --c-blue-2: #42a5f5; + + --shadow-sm: 0 1px 3px rgba(0,0,0,0.08); + --shadow-overlay: 0 2px 4px rgba(0,0,0,0.04); + --shadow-primary-2: 0 2px 6px rgba(30, 136, 229, 0.3); + --shadow-primary-4: 0 4px 8px rgba(30, 136, 229, 0.4); + --shadow-purple-2: 0 2px 6px rgba(102, 126, 234, 0.3); + --shadow-purple-4: 0 4px 8px rgba(102, 126, 234, 0.4); + + --grad-primary: linear-gradient(135deg, var(--c-primary) 0%, var(--c-primary-dark) 100%); + --grad-purple: linear-gradient(135deg, var(--c-purple) 0%, var(--c-purple-dark) 100%); + --grad-blue: linear-gradient(135deg, var(--c-blue-2) 0%, var(--c-primary) 100%); + --grad-toolbar: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); + --grad-toolbar-bottom: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%); + --grad-xhs-bg: linear-gradient(135deg, #f5f7fa 0%, #e8eaf6 100%); +} + +/* 通用按钮外观(不含背景与尺寸) */ +.copy-button, +.refresh-button, +.toolbar-button, +.msg-ok-btn, +.xhs-slice-btn { + border: none; + border-radius: 6px; + cursor: pointer; + font-weight: 500; + transition: all 0.2s ease; +} + +/* 通用按钮 hover 的位移效果(各自保留独立阴影) */ +.copy-button:hover, +.refresh-button:hover, +.toolbar-button:hover, +.msg-ok-btn:hover { + transform: translateY(-1px); +} + +/* 下拉选择的通用外观(各自保留尺寸差异) */ +.platform-select, +.wechat-select, +.style-select { + border: 1px solid var(--c-border); + border-radius: 6px; + background: white; + font-size: 13px; + cursor: pointer; + transition: all 0.2s ease; + box-shadow: var(--shadow-sm); +} + +/* 平台与公众号选择的相同 hover/focus 效果(style-select 单独增强) */ +.platform-select:hover, +.wechat-select:hover { border-color: var(--c-primary); } +.platform-select:focus, +.wechat-select:focus { outline: none; border-color: var(--c-primary); } .note-preview { + grid-template-rows: auto 1fr; + grid-template-columns: 1fr; + display: grid; min-height: 100%; width: 100%; height: 100%; - background-color: #fff; - display: flex; - flex-direction: column; + background-color: var(--c-bg); } /* 预览内部平台容器需要可伸缩: */ -.wechat-preview-container, .xiaohongshu-preview-container { +.wechat-preview-container:not([style*="display: none"]), +.xiaohongshu-preview-container:not([style*="display: none"]) { flex: 1; - display: flex; - flex-direction: column; + display: grid !important; + grid-template-rows: auto 1fr; min-height: 0; /* 允许内部滚动区域正确计算高度 */ } .render-div { - flex: 1; overflow-y: auto; padding: 10px; -webkit-user-select: text; @@ -44,55 +112,43 @@ .preview-toolbar { position: relative; - min-height: 100px; - padding: 4px 0; + 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: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); - box-shadow: 0 2px 4px rgba(0,0,0,0.04); + background: var(--grad-toolbar); + box-shadow: var(--shadow-overlay); } .copy-button { margin-right: 10px; padding: 6px 14px; - background: linear-gradient(135deg, #1e88e5 0%, #1565c0 100%); + background: var(--grad-primary); color: white; - border: none; - border-radius: 6px; - cursor: pointer; font-size: 13px; - font-weight: 500; - transition: all 0.2s ease; - box-shadow: 0 2px 6px rgba(30, 136, 229, 0.3); + box-shadow: var(--shadow-primary-2); } -.copy-button:hover { - transform: translateY(-1px); - box-shadow: 0 4px 8px rgba(30, 136, 229, 0.4); -} +.copy-button:hover { box-shadow: var(--shadow-primary-4); } .refresh-button { margin-right: 10px; padding: 6px 14px; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + background: var(--grad-purple); color: white; - border: none; - border-radius: 6px; - cursor: pointer; font-size: 13px; - font-weight: 500; - transition: all 0.2s ease; - box-shadow: 0 2px 6px rgba(102, 126, 234, 0.3); + box-shadow: var(--shadow-purple-2); } -.refresh-button:hover { - transform: translateY(-1px); - box-shadow: 0 4px 8px rgba(102, 126, 234, 0.4); -} +.refresh-button:hover { box-shadow: var(--shadow-purple-4); } .upload-input { margin-left: 10px; padding: 6px 10px; - border: 1px solid #dadce0; + border: 1px solid var(--c-border); border-radius: 6px; font-size: 13px; transition: all 0.2s ease; @@ -102,9 +158,10 @@ cursor: pointer; } -.upload-input:focus { +.upload-input:focus, +.style-select:focus { outline: none; - border-color: #1e88e5; + border-color: var(--c-primary); box-shadow: 0 0 0 3px rgba(30, 136, 229, 0.1); } @@ -114,26 +171,24 @@ height: 16px; margin: 0 6px 0 0; cursor: pointer; - accent-color: #1e88e5; + accent-color: var(--c-primary); } /* Label 标签样式 */ label { font-size: 13px; - color: #5f6368; + color: var(--c-text-muted); cursor: pointer; user-select: none; transition: color 0.2s ease; } -label:hover { - color: #1e88e5; -} +label:hover { color: var(--c-primary); } .style-label { margin-right: 10px; font-size: 13px; - color: #5f6368; + color: var(--c-text-muted); font-weight: 500; white-space: nowrap; } @@ -142,25 +197,14 @@ label:hover { margin-right: 10px; width: 120px; padding: 6px 10px; - border: 1px solid #dadce0; - border-radius: 6px; - background: white; - font-size: 13px; - cursor: pointer; - transition: all 0.2s ease; - box-shadow: 0 1px 3px rgba(0,0,0,0.1); } .style-select:hover { - border-color: #1e88e5; + border-color: var(--c-primary); box-shadow: 0 2px 6px rgba(30, 136, 229, 0.2); } -.style-select:focus { - outline: none; - border-color: #1e88e5; - box-shadow: 0 0 0 3px rgba(30, 136, 229, 0.1); -} +/* focus 规则见与 .upload-input:focus 的组合声明 */ .msg-view { position: absolute; @@ -186,22 +230,14 @@ label:hover { .msg-ok-btn { padding: 10px 24px; margin: 0 8px; - background: linear-gradient(135deg, #1e88e5 0%, #1565c0 100%); + background: var(--grad-primary); color: white; - border: none; - border-radius: 6px; - cursor: pointer; font-size: 14px; - font-weight: 500; - transition: all 0.2s ease; - box-shadow: 0 2px 6px rgba(30, 136, 229, 0.3); + box-shadow: var(--shadow-primary-2); min-width: 80px; } -.msg-ok-btn:hover { - transform: translateY(-1px); - box-shadow: 0 4px 8px rgba(30, 136, 229, 0.4); -} +.msg-ok-btn:hover { box-shadow: var(--shadow-primary-4); } .msg-ok-btn:active { transform: translateY(0); @@ -214,7 +250,9 @@ label:hover { border-radius: 10px; } .note-mpcard-content { - display: flex; + display: grid; + grid-auto-flow: column; + align-items: center; } .note-mpcard-headimg { border: none !important; @@ -246,11 +284,10 @@ label:hover { } .loading-wrapper { - display: flex; + display: grid; width: 100%; height: 100%; - align-items: center; - justify-content: center; + place-items: center; } .loading-spinner { @@ -276,23 +313,38 @@ label:hover { /* =========================================================== */ .toolbar-line { - display: flex; + display: grid; + grid-auto-flow: column; align-items: center; gap: 12px; padding: 8px 12px; background: white; border-radius: 6px; margin: 8px 10px; - box-shadow: 0 1px 3px rgba(0,0,0,0.08); + box-shadow: var(--shadow-sm); } .toolbar-line.flex-wrap { - flex-wrap: 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 #1e88e5; + border-left: 4px solid var(--c-primary); +} + +/* 平台选择容器:单层 Grid 排列 */ +.platform-chooser-container.platform-chooser-grid { + display: grid; + grid-auto-flow: column; + align-items: center; + gap: 12px; + padding: 8px 12px; + background: white; /* 被 .platform-selector-line 的背景覆写 */ + border-radius: 6px; + margin: 8px 10px; + box-shadow: var(--shadow-sm); } /* =========================================================== */ @@ -301,81 +353,39 @@ label:hover { .platform-select { padding: 6px 12px; - border: 1px solid #dadce0; - border-radius: 6px; - background: white; - font-size: 13px; - cursor: pointer; - transition: all 0.2s ease; - box-shadow: 0 1px 3px rgba(0,0,0,0.1); min-width: 150px; font-weight: 500; } -.platform-select:hover { - border-color: #1e88e5; -} - -.platform-select:focus { - outline: none; - border-color: #1e88e5; -} - /* =========================================================== */ /* 微信公众号选择器样式 */ /* =========================================================== */ .wechat-select { padding: 6px 12px; - border: 1px solid #dadce0; - border-radius: 6px; - background: white; - font-size: 13px; - cursor: pointer; - transition: all 0.2s ease; - box-shadow: 0 1px 3px rgba(0,0,0,0.1); min-width: 200px; } -.wechat-select:hover { - border-color: #1e88e5; -} - -.wechat-select:focus { - outline: none; - border-color: #1e88e5; -} - /* =========================================================== */ /* 按钮样式 */ /* =========================================================== */ .toolbar-button { padding: 6px 14px; - background: linear-gradient(135deg, #1e88e5 0%, #1565c0 100%); + background: var(--grad-primary); color: white; - border: none; - border-radius: 6px; - cursor: pointer; font-size: 13px; - font-weight: 500; - transition: all 0.2s ease; - box-shadow: 0 2px 6px rgba(30, 136, 229, 0.3); + box-shadow: var(--shadow-primary-2); } -.toolbar-button:hover { - transform: translateY(-1px); - box-shadow: 0 4px 8px rgba(30, 136, 229, 0.4); -} +.toolbar-button:hover { box-shadow: var(--shadow-primary-4); } .toolbar-button.purple-gradient { - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - box-shadow: 0 2px 6px rgba(102, 126, 234, 0.3); + background: var(--grad-purple); + box-shadow: var(--shadow-purple-2); } -.toolbar-button.purple-gradient:hover { - box-shadow: 0 4px 8px rgba(102, 126, 234, 0.4); -} +.toolbar-button.purple-gradient:hover { box-shadow: var(--shadow-purple-4); } /* =========================================================== */ /* 分隔线样式 */ @@ -384,7 +394,7 @@ label:hover { .toolbar-separator { width: 1px; height: 24px; - background: #dadce0; + background: var(--c-border); margin: 0 4px; } @@ -398,8 +408,10 @@ label:hover { } .doc-modal-content { - display: flex; - flex-direction: column; + display: grid; + grid-template-rows: auto auto 1fr; + row-gap: 8px; + min-height: 0; } .doc-modal-title { @@ -413,7 +425,7 @@ label:hover { } .doc-modal-iframe { - flex: 1; + min-height: 0; } /* =========================================================== */ @@ -421,9 +433,10 @@ label:hover { /* =========================================================== */ .setting-help-section { - display: flex; - flex-direction: row; + display: grid; + grid-auto-flow: column; align-items: center; + column-gap: 10px; } .setting-help-title { @@ -449,40 +462,36 @@ label:hover { height: 100%; } -.xhs-preview-container { - display: flex; - flex-direction: column; +.xhs-preview-container:not([style*="display: none"]) { + display: grid !important; + grid-template-rows: auto 1fr auto; height: 100%; - background: linear-gradient(135deg, #f5f7fa 0%, #e8eaf6 100%); + background: var(--grad-xhs-bg); + min-height: 0; } .xhs-page-container { - flex: 1; overflow-y: auto; overflow-x: hidden; - display: flex; - flex-direction: column; - align-items: center; + 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; /* 允许 flex 子项正确收缩和滚动 */ + min-height: 0; /* 允许子项正确收缩和滚动 */ } /* 小红书单页包裹器:为缩放后的页面预留正确的布局空间 */ .xhs-page-wrapper { - /* 显示尺寸(缩放后):540 × 720 */ - width: 540px; - height: 720px; margin: 0px auto; position: relative; - overflow: visible; + overflow: hidden; } /* 小红书单页样式:实际尺寸 1080×1440,通过 scale 缩放到 540×720 */ .xhs-page { - /* 实际尺寸由 renderPage 设置(1080×1440) */ + /* 实际尺寸与缩放由代码在运行时设置 */ transform-origin: top left; - transform: scale(0.5); /* 540/1080 = 0.5 */ background: white; box-shadow: 0 4px 12px rgba(0,0,0,0.1); border-radius: 8px; @@ -494,26 +503,26 @@ label:hover { } .xhs-top-toolbar { - display: flex; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(140px, max-content)); align-items: center; gap: 12px; padding: 8px 12px; - background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); + background: var(--grad-toolbar); border-bottom: 1px solid #e8eaed; - box-shadow: 0 2px 4px rgba(0,0,0,0.04); - flex-wrap: wrap; + box-shadow: var(--shadow-overlay); } .toolbar-label { font-size: 11px; - color: #5f6368; + color: var(--c-text-muted); font-weight: 500; white-space: nowrap; } .xhs-select { padding: 4px 8px; - border: 1px solid #dadce0; + border: 1px solid var(--c-border); border-radius: 4px; background: white; font-size: 11px; @@ -522,20 +531,21 @@ label:hover { } .xhs-select:hover { - border-color: #1e88e5; + border-color: var(--c-primary); } .xhs-select:focus { outline: none; - border-color: #1e88e5; + border-color: var(--c-primary); } .font-size-group { - display: flex; + display: grid; + grid-auto-flow: column; align-items: center; gap: 6px; background: white; - border: 1px solid #dadce0; + border: 1px solid var(--c-border); border-radius: 4px; padding: 2px; } @@ -565,7 +575,8 @@ label:hover { } .xhs-page-navigation { - display: flex; + display: grid; + grid-auto-flow: column; justify-content: center; align-items: center; gap: 16px; @@ -577,20 +588,20 @@ label:hover { .xhs-nav-btn { width: 36px; height: 36px; - border: 1px solid #dadce0; + border: 1px solid var(--c-border); border-radius: 50%; cursor: pointer; font-size: 20px; background: white; color: #5f6368; transition: all 0.2s ease; - box-shadow: 0 1px 3px rgba(0,0,0,0.08); + box-shadow: var(--shadow-sm); } .xhs-nav-btn:hover { - background: linear-gradient(135deg, #1e88e5 0%, #1565c0 100%); + background: var(--grad-primary); color: white; - border-color: #1e88e5; + border-color: var(--c-primary); } .xhs-page-number { @@ -602,26 +613,22 @@ label:hover { } .xhs-bottom-toolbar { - display: flex; + display: grid; + grid-auto-flow: column; justify-content: center; gap: 12px; padding: 12px 16px; - background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%); + 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: linear-gradient(135deg, #1e88e5 0%, #1565c0 100%); + background: var(--grad-primary); color: white; - border: none; - border-radius: 6px; - cursor: pointer; font-size: 13px; - font-weight: 500; - transition: all 0.2s ease; - box-shadow: 0 2px 6px rgba(30, 136, 229, 0.3); + box-shadow: var(--shadow-primary-2); } .xhs-slice-btn:hover { @@ -630,7 +637,7 @@ label:hover { } .xhs-slice-btn.secondary { - background: linear-gradient(135deg, #42a5f5 0%, #1e88e5 100%); + background: var(--grad-blue); box-shadow: 0 2px 6px rgba(66, 165, 245, 0.3); } @@ -660,7 +667,8 @@ label:hover { } .xhs-code-container { - display: flex; + display: grid; + grid-template-columns: auto 1fr auto; align-items: center; gap: 10px; margin-bottom: 20px; @@ -704,7 +712,8 @@ label:hover { } .xhs-button-container { - display: flex; + display: grid; + grid-auto-flow: column; justify-content: center; gap: 15px; margin-top: 20px; diff --git a/todolist.md b/todolist.md index 51af40b..477d877 100644 --- a/todolist.md +++ b/todolist.md @@ -103,7 +103,10 @@ SOLVE:obsidian控制台打印信息,定位在哪里阻塞,AI修复。 - 字变大时,一页的内容放不下,重新分页应该会增加页数。但现在重新分页当前页放不下的内容只是被剪掉了。 - 表格显示不完整。 -9. styles.css中有很多冗余。改为grid布局。 +9. styles.css中有很多冗余。改为grid布局。部分完成,这部分需要后面**手动调整**重构。🧶 ♻️ ❇️ 问题:小红书预览布局有问题❓ +10. 新建docs文件夹,把除了README和todolist以外的markdown文件放到docs中。 +✅ +