Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d32c0f5e7 | ||
|
|
1c8449b04a | ||
|
|
cbf32b3f0b |
20
build.sh
@@ -4,16 +4,24 @@ set -e # 出错立即退出
|
|||||||
# 1. 构建
|
# 1. 构建
|
||||||
npm run build
|
npm run build
|
||||||
|
|
||||||
# 2. 目标路径
|
# 2. 目标目录
|
||||||
TARGET=~/myweb/.obsidian/plugins/note-to-mp/main.js
|
PLUGIN_DIR=~/myweb/.obsidian/plugins/note-to-mp
|
||||||
BACKUP=~/myweb/.obsidian/plugins/note-to-mp/main.js.bk
|
FILES=("main.js" "styles.css" "manifest.json")
|
||||||
|
|
||||||
|
# 3. 遍历文件,逐一备份并覆盖
|
||||||
|
for FILE in "${FILES[@]}"; do
|
||||||
|
TARGET="$PLUGIN_DIR/$FILE"
|
||||||
|
BACKUP="$PLUGIN_DIR/backup/$FILE.bk"
|
||||||
|
|
||||||
# 3. 如果存在 main.js,先备份
|
|
||||||
if [ -f "$TARGET" ]; then
|
if [ -f "$TARGET" ]; then
|
||||||
cp -f "$TARGET" "$BACKUP"
|
cp -f "$TARGET" "$BACKUP"
|
||||||
echo "已备份 $TARGET -> $BACKUP"
|
echo "已备份 $TARGET -> $BACKUP"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 4. 覆盖复制新的 main.js
|
if [ -f "$FILE" ]; then
|
||||||
cp -f main.js "$TARGET"
|
cp -f "$FILE" "$TARGET"
|
||||||
echo "已更新 $TARGET"
|
echo "已更新 $TARGET"
|
||||||
|
else
|
||||||
|
echo "⚠️ 源文件 $FILE 不存在,跳过"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 201 KiB After Width: | Height: | Size: 143 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 1.9 MiB |
|
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 1.9 MiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 67 KiB |
@@ -19,26 +19,21 @@ export class DocModal extends Modal {
|
|||||||
|
|
||||||
onOpen() {
|
onOpen() {
|
||||||
let { contentEl, modalEl } = this;
|
let { contentEl, modalEl } = this;
|
||||||
modalEl.style.width = '640px';
|
modalEl.addClass('doc-modal');
|
||||||
modalEl.style.height = '720px';
|
contentEl.addClass('doc-modal-content');
|
||||||
contentEl.style.display = 'flex';
|
|
||||||
contentEl.style.flexDirection = 'column';
|
|
||||||
|
|
||||||
const titleEl = contentEl.createEl('h2', { text: this.title });
|
const titleEl = contentEl.createEl('h2', { text: this.title, cls: 'doc-modal-title' });
|
||||||
titleEl.style.marginTop = '0.5em';
|
const content = contentEl.createEl('div', { cls: 'doc-modal-desc' });
|
||||||
const content = contentEl.createEl('div');
|
|
||||||
content.setAttr('style', 'margin-bottom:1em;-webkit-user-select: text; user-select: text;');
|
|
||||||
content.appendChild(sanitizeHTMLToDom(this.content));
|
content.appendChild(sanitizeHTMLToDom(this.content));
|
||||||
|
|
||||||
const iframe = contentEl.createEl('iframe', {
|
const iframe = contentEl.createEl('iframe', {
|
||||||
|
cls: 'doc-modal-iframe',
|
||||||
attr: {
|
attr: {
|
||||||
src: this.url,
|
src: this.url,
|
||||||
width: '100%',
|
width: '100%',
|
||||||
allow: 'clipboard-read; clipboard-write',
|
allow: 'clipboard-read; clipboard-write',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
iframe.style.flex = '1';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onClose() {
|
onClose() {
|
||||||
|
|||||||
39
src/main.ts
@@ -38,6 +38,7 @@ import { XiaohongshuAPIManager } from './xiaohongshu/api';
|
|||||||
export default class NoteToMpPlugin extends Plugin {
|
export default class NoteToMpPlugin extends Plugin {
|
||||||
settings: NMPSettings;
|
settings: NMPSettings;
|
||||||
assetsManager: AssetsManager;
|
assetsManager: AssetsManager;
|
||||||
|
ribbonIconEl: HTMLElement | null = null;
|
||||||
constructor(app: App, manifest: PluginManifest) {
|
constructor(app: App, manifest: PluginManifest) {
|
||||||
super(app, manifest);
|
super(app, manifest);
|
||||||
AssetsManager.setup(app, manifest);
|
AssetsManager.setup(app, manifest);
|
||||||
@@ -55,6 +56,12 @@ export default class NoteToMpPlugin extends Plugin {
|
|||||||
uevent('load');
|
uevent('load');
|
||||||
this.app.workspace.onLayoutReady(()=>{
|
this.app.workspace.onLayoutReady(()=>{
|
||||||
this.loadResource();
|
this.loadResource();
|
||||||
|
// 布局就绪后清理旧视图并自动打开一个新的标准预览(可选)
|
||||||
|
this.cleanupLegacyViews();
|
||||||
|
// 如果当前没有我们的预览叶子,自动激活一次,改善首次体验
|
||||||
|
if (this.app.workspace.getLeavesOfType(VIEW_TYPE_NOTE_PREVIEW).length === 0) {
|
||||||
|
this.activateView();
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
this.registerView(
|
this.registerView(
|
||||||
@@ -62,10 +69,10 @@ export default class NoteToMpPlugin extends Plugin {
|
|||||||
(leaf) => new NotePreview(leaf, this)
|
(leaf) => new NotePreview(leaf, this)
|
||||||
);
|
);
|
||||||
|
|
||||||
const ribbonIconEl = this.addRibbonIcon('clipboard-paste', '复制到公众号', (evt: MouseEvent) => {
|
this.ribbonIconEl = this.addRibbonIcon('clipboard-paste', '复制到公众号', (evt: MouseEvent) => {
|
||||||
this.activateView();
|
this.activateView();
|
||||||
});
|
});
|
||||||
ribbonIconEl.addClass('note-to-mp-plugin-ribbon-class');
|
this.ribbonIconEl.addClass('note-to-mp-plugin-ribbon-class');
|
||||||
|
|
||||||
this.addCommand({
|
this.addCommand({
|
||||||
id: 'note-to-mp-preview',
|
id: 'note-to-mp-preview',
|
||||||
@@ -146,7 +153,35 @@ export default class NoteToMpPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onunload() {
|
onunload() {
|
||||||
|
console.log('Unloading NoteToMP');
|
||||||
|
// 移除 ribbon icon,避免重载插件时重复创建
|
||||||
|
if (this.ribbonIconEl) {
|
||||||
|
this.ribbonIconEl.remove();
|
||||||
|
this.ribbonIconEl = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理历史失效视图:
|
||||||
|
* 某些用户可能曾使用过旧插件构建(例如 note-mp-preview-manager),升级后残留的标签页会提示“插件不再活动”。
|
||||||
|
* 这里做一次性清理,避免用户手动关标签造成困扰。
|
||||||
|
*/
|
||||||
|
private cleanupLegacyViews() {
|
||||||
|
try {
|
||||||
|
const legacyIds = ['note-mp-preview-manager']; // 可扩展
|
||||||
|
const { workspace } = this.app;
|
||||||
|
// 遍历所有叶子,关闭可能的失效 view(无法直接匹配 id 时,仅检测报错视图类型)
|
||||||
|
workspace.getLeavesOfType(VIEW_TYPE_NOTE_PREVIEW).forEach(l => {
|
||||||
|
// 如果 view 的 plugin 不存在或 manifest id 不匹配我们当前的 id,则关闭
|
||||||
|
const anyView: any = l.view;
|
||||||
|
const vid = (anyView?.plugin?.manifest?.id) || '';
|
||||||
|
if (vid && vid !== this.manifest.id && legacyIds.includes(vid)) {
|
||||||
|
workspace.detachLeavesOfType(VIEW_TYPE_NOTE_PREVIEW);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('[NoteToMp] cleanupLegacyViews 失败', e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadSettings() {
|
async loadSettings() {
|
||||||
|
|||||||
@@ -200,14 +200,11 @@ export class NotePreview extends ItemView {
|
|||||||
|
|
||||||
// 平台选择器(新增)- 始终显示
|
// 平台选择器(新增)- 始终显示
|
||||||
lineDiv = this.toolbar.createDiv({ cls: 'toolbar-line platform-selector-line' });
|
lineDiv = this.toolbar.createDiv({ cls: 'toolbar-line platform-selector-line' });
|
||||||
lineDiv.style.cssText = 'display: flex; align-items: center; gap: 12px; padding: 8px 12px; background: linear-gradient(135deg, #fff3e0 0%, #ffffff 100%); border-left: 4px solid #1e88e5; border-radius: 6px; margin: 8px 10px;';
|
|
||||||
|
|
||||||
const platformLabel = lineDiv.createDiv({ cls: 'style-label' });
|
const platformLabel = lineDiv.createDiv({ cls: 'style-label' });
|
||||||
platformLabel.innerText = '发布平台';
|
platformLabel.innerText = '发布平台';
|
||||||
platformLabel.style.cssText = 'font-size: 13px; color: #5f6368; font-weight: 500; white-space: nowrap;';
|
|
||||||
|
|
||||||
const platformSelect = lineDiv.createEl('select', { cls: 'style-select' });
|
const platformSelect = lineDiv.createEl('select', { cls: 'platform-select' });
|
||||||
platformSelect.style.cssText = '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;';
|
|
||||||
|
|
||||||
// 添加平台选项
|
// 添加平台选项
|
||||||
const wechatOption = platformSelect.createEl('option');
|
const wechatOption = platformSelect.createEl('option');
|
||||||
@@ -229,14 +226,11 @@ export class NotePreview extends ItemView {
|
|||||||
// 公众号
|
// 公众号
|
||||||
if (this.settings.wxInfo.length > 1 || Platform.isDesktop) {
|
if (this.settings.wxInfo.length > 1 || Platform.isDesktop) {
|
||||||
lineDiv = this.toolbar.createDiv({ cls: 'toolbar-line wechat-only' });
|
lineDiv = this.toolbar.createDiv({ cls: 'toolbar-line wechat-only' });
|
||||||
lineDiv.style.cssText = 'display: flex; 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);';
|
|
||||||
|
|
||||||
const wxLabel = lineDiv.createDiv({ cls: 'style-label' });
|
const wxLabel = lineDiv.createDiv({ cls: 'style-label' });
|
||||||
wxLabel.innerText = '公众号';
|
wxLabel.innerText = '公众号';
|
||||||
wxLabel.style.cssText = 'font-size: 13px; color: #5f6368; font-weight: 500; white-space: nowrap;';
|
|
||||||
|
|
||||||
const wxSelect = lineDiv.createEl('select', { cls: 'style-select' });
|
const wxSelect = lineDiv.createEl('select', { cls: 'wechat-select' });
|
||||||
wxSelect.style.cssText = '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;';
|
|
||||||
wxSelect.onchange = async () => {
|
wxSelect.onchange = async () => {
|
||||||
this.currentAppId = wxSelect.value;
|
this.currentAppId = wxSelect.value;
|
||||||
this.onAppIdChanged();
|
this.onAppIdChanged();
|
||||||
@@ -258,13 +252,9 @@ export class NotePreview extends ItemView {
|
|||||||
|
|
||||||
if (Platform.isDesktop) {
|
if (Platform.isDesktop) {
|
||||||
// 分隔线
|
// 分隔线
|
||||||
const separator = lineDiv.createDiv();
|
const separator = lineDiv.createDiv({ cls: 'toolbar-separator' });
|
||||||
separator.style.cssText = 'width: 1px; height: 24px; background: #dadce0; margin: 0 4px;';
|
|
||||||
|
|
||||||
const openBtn = lineDiv.createEl('button', { text: '🌐 去公众号后台' });
|
const openBtn = lineDiv.createEl('button', { text: '🌐 去公众号后台', cls: 'toolbar-button purple-gradient' });
|
||||||
openBtn.style.cssText = 'padding: 6px 14px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); 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);';
|
|
||||||
openBtn.onmouseenter = () => openBtn.style.transform = 'translateY(-1px)';
|
|
||||||
openBtn.onmouseleave = () => openBtn.style.transform = 'translateY(0)';
|
|
||||||
|
|
||||||
openBtn.onclick = async () => {
|
openBtn.onclick = async () => {
|
||||||
const { shell } = require('electron');
|
const { shell } = require('electron');
|
||||||
@@ -278,13 +268,9 @@ export class NotePreview extends ItemView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 复制,刷新,带图片复制,发草稿箱
|
// 复制,刷新,带图片复制,发草稿箱
|
||||||
lineDiv = this.toolbar.createDiv({ cls: 'toolbar-line wechat-only' });
|
lineDiv = this.toolbar.createDiv({ cls: 'toolbar-line wechat-only flex-wrap' });
|
||||||
lineDiv.style.cssText = 'display: flex; 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); flex-wrap: wrap;';
|
|
||||||
|
|
||||||
const refreshBtn = lineDiv.createEl('button', { text: '🔄 刷新' });
|
const refreshBtn = lineDiv.createEl('button', { text: '🔄 刷新', cls: 'toolbar-button purple-gradient' });
|
||||||
refreshBtn.style.cssText = 'padding: 6px 14px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); 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);';
|
|
||||||
refreshBtn.onmouseenter = () => refreshBtn.style.transform = 'translateY(-1px)';
|
|
||||||
refreshBtn.onmouseleave = () => refreshBtn.style.transform = 'translateY(0)';
|
|
||||||
|
|
||||||
refreshBtn.onclick = async () => {
|
refreshBtn.onclick = async () => {
|
||||||
await this.assetsManager.loadCustomCSS();
|
await this.assetsManager.loadCustomCSS();
|
||||||
@@ -294,10 +280,7 @@ export class NotePreview extends ItemView {
|
|||||||
uevent('refresh');
|
uevent('refresh');
|
||||||
}
|
}
|
||||||
if (Platform.isDesktop) {
|
if (Platform.isDesktop) {
|
||||||
const copyBtn = lineDiv.createEl('button', { text: '📋 复制' });
|
const copyBtn = lineDiv.createEl('button', { text: '📋 复制', cls: 'toolbar-button' });
|
||||||
copyBtn.style.cssText = 'padding: 6px 14px; background: linear-gradient(135deg, #1e88e5 0%, #1565c0 100%); 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);';
|
|
||||||
copyBtn.onmouseenter = () => copyBtn.style.transform = 'translateY(-1px)';
|
|
||||||
copyBtn.onmouseleave = () => copyBtn.style.transform = 'translateY(0)';
|
|
||||||
|
|
||||||
copyBtn.onclick = async() => {
|
copyBtn.onclick = async() => {
|
||||||
try {
|
try {
|
||||||
@@ -311,30 +294,21 @@ export class NotePreview extends ItemView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const uploadImgBtn = lineDiv.createEl('button', { text: '📤 上传图片' });
|
const uploadImgBtn = lineDiv.createEl('button', { text: '📤 上传图片', cls: 'toolbar-button' });
|
||||||
uploadImgBtn.style.cssText = 'padding: 6px 14px; background: linear-gradient(135deg, #1e88e5 0%, #1565c0 100%); 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);';
|
|
||||||
uploadImgBtn.onmouseenter = () => uploadImgBtn.style.transform = 'translateY(-1px)';
|
|
||||||
uploadImgBtn.onmouseleave = () => uploadImgBtn.style.transform = 'translateY(0)';
|
|
||||||
|
|
||||||
uploadImgBtn.onclick = async() => {
|
uploadImgBtn.onclick = async() => {
|
||||||
await this.uploadImages();
|
await this.uploadImages();
|
||||||
uevent('upload');
|
uevent('upload');
|
||||||
}
|
}
|
||||||
|
|
||||||
const postBtn = lineDiv.createEl('button', { text: '📝 发草稿' });
|
const postBtn = lineDiv.createEl('button', { text: '📝 发草稿', cls: 'toolbar-button' });
|
||||||
postBtn.style.cssText = 'padding: 6px 14px; background: linear-gradient(135deg, #1e88e5 0%, #1565c0 100%); 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);';
|
|
||||||
postBtn.onmouseenter = () => postBtn.style.transform = 'translateY(-1px)';
|
|
||||||
postBtn.onmouseleave = () => postBtn.style.transform = 'translateY(0)';
|
|
||||||
|
|
||||||
postBtn.onclick = async() => {
|
postBtn.onclick = async() => {
|
||||||
await this.postArticle();
|
await this.postArticle();
|
||||||
uevent('pub');
|
uevent('pub');
|
||||||
}
|
}
|
||||||
|
|
||||||
const imagesBtn = lineDiv.createEl('button', { text: '🖼️ 图片/文字' });
|
const imagesBtn = lineDiv.createEl('button', { text: '🖼️ 图片/文字', cls: 'toolbar-button' });
|
||||||
imagesBtn.style.cssText = 'padding: 6px 14px; background: linear-gradient(135deg, #1e88e5 0%, #1565c0 100%); 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);';
|
|
||||||
imagesBtn.onmouseenter = () => imagesBtn.style.transform = 'translateY(-1px)';
|
|
||||||
imagesBtn.onmouseleave = () => imagesBtn.style.transform = 'translateY(0)';
|
|
||||||
|
|
||||||
imagesBtn.onclick = async() => {
|
imagesBtn.onclick = async() => {
|
||||||
await this.postImages();
|
await this.postImages();
|
||||||
@@ -342,10 +316,7 @@ export class NotePreview extends ItemView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Platform.isDesktop && this.settings.isAuthKeyVaild()) {
|
if (Platform.isDesktop && this.settings.isAuthKeyVaild()) {
|
||||||
const htmlBtn = lineDiv.createEl('button', { text: '💾 导出HTML' });
|
const htmlBtn = lineDiv.createEl('button', { text: '💾 导出HTML', cls: 'toolbar-button' });
|
||||||
htmlBtn.style.cssText = 'padding: 6px 14px; background: linear-gradient(135deg, #1e88e5 0%, #1565c0 100%); 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);';
|
|
||||||
htmlBtn.onmouseenter = () => htmlBtn.style.transform = 'translateY(-1px)';
|
|
||||||
htmlBtn.onmouseleave = () => htmlBtn.style.transform = 'translateY(0)';
|
|
||||||
|
|
||||||
htmlBtn.onclick = async() => {
|
htmlBtn.onclick = async() => {
|
||||||
await this.exportHTML();
|
await this.exportHTML();
|
||||||
@@ -355,11 +326,9 @@ export class NotePreview extends ItemView {
|
|||||||
|
|
||||||
// 封面
|
// 封面
|
||||||
lineDiv = this.toolbar.createDiv({ cls: 'toolbar-line wechat-only' });
|
lineDiv = this.toolbar.createDiv({ cls: 'toolbar-line wechat-only' });
|
||||||
lineDiv.style.cssText = 'display: flex; 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);';
|
|
||||||
|
|
||||||
const coverTitle = lineDiv.createDiv({ cls: 'style-label' });
|
const coverTitle = lineDiv.createDiv({ cls: 'style-label' });
|
||||||
coverTitle.innerText = '封面';
|
coverTitle.innerText = '封面';
|
||||||
coverTitle.style.cssText = 'font-size: 13px; color: #5f6368; font-weight: 500; white-space: nowrap;';
|
|
||||||
|
|
||||||
this.useDefaultCover = lineDiv.createEl('input', { cls: 'input-style' });
|
this.useDefaultCover = lineDiv.createEl('input', { cls: 'input-style' });
|
||||||
this.useDefaultCover.setAttr('type', 'radio');
|
this.useDefaultCover.setAttr('type', 'radio');
|
||||||
@@ -378,7 +347,6 @@ export class NotePreview extends ItemView {
|
|||||||
const defaultLable = lineDiv.createEl('label');
|
const defaultLable = lineDiv.createEl('label');
|
||||||
defaultLable.innerText = '默认';
|
defaultLable.innerText = '默认';
|
||||||
defaultLable.setAttr('for', 'default-cover');
|
defaultLable.setAttr('for', 'default-cover');
|
||||||
defaultLable.style.cssText = 'font-size: 13px; color: #5f6368; cursor: pointer; user-select: none;';
|
|
||||||
|
|
||||||
this.useLocalCover = lineDiv.createEl('input', { cls: 'input-style' });
|
this.useLocalCover = lineDiv.createEl('input', { cls: 'input-style' });
|
||||||
this.useLocalCover.setAttr('type', 'radio');
|
this.useLocalCover.setAttr('type', 'radio');
|
||||||
@@ -398,7 +366,6 @@ export class NotePreview extends ItemView {
|
|||||||
const localLabel = lineDiv.createEl('label');
|
const localLabel = lineDiv.createEl('label');
|
||||||
localLabel.setAttr('for', 'local-cover');
|
localLabel.setAttr('for', 'local-cover');
|
||||||
localLabel.innerText = '上传';
|
localLabel.innerText = '上传';
|
||||||
localLabel.style.cssText = 'font-size: 13px; color: #5f6368; cursor: pointer; user-select: none;';
|
|
||||||
|
|
||||||
this.coverEl = lineDiv.createEl('input', { cls: 'upload-input' });
|
this.coverEl = lineDiv.createEl('input', { cls: 'upload-input' });
|
||||||
this.coverEl.setAttr('type', 'file');
|
this.coverEl.setAttr('type', 'file');
|
||||||
@@ -409,15 +376,12 @@ export class NotePreview extends ItemView {
|
|||||||
|
|
||||||
// 样式
|
// 样式
|
||||||
if (this.settings.showStyleUI) {
|
if (this.settings.showStyleUI) {
|
||||||
lineDiv = this.toolbar.createDiv({ cls: 'toolbar-line wechat-only' });
|
lineDiv = this.toolbar.createDiv({ cls: 'toolbar-line wechat-only flex-wrap' });
|
||||||
lineDiv.style.cssText = 'display: flex; 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); flex-wrap: wrap;';
|
|
||||||
|
|
||||||
const cssStyle = lineDiv.createDiv({ cls: 'style-label' });
|
const cssStyle = lineDiv.createDiv({ cls: 'style-label' });
|
||||||
cssStyle.innerText = '样式';
|
cssStyle.innerText = '样式';
|
||||||
cssStyle.style.cssText = 'font-size: 13px; color: #5f6368; font-weight: 500; white-space: nowrap;';
|
|
||||||
|
|
||||||
const selectBtn = lineDiv.createEl('select', { cls: 'style-select' });
|
const selectBtn = lineDiv.createEl('select', { cls: 'style-select' });
|
||||||
selectBtn.style.cssText = '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: 120px;';
|
|
||||||
|
|
||||||
selectBtn.onchange = async () => {
|
selectBtn.onchange = async () => {
|
||||||
this.currentTheme = selectBtn.value;
|
this.currentTheme = selectBtn.value;
|
||||||
@@ -434,15 +398,12 @@ export class NotePreview extends ItemView {
|
|||||||
this.themeSelect = selectBtn;
|
this.themeSelect = selectBtn;
|
||||||
|
|
||||||
// 分隔线
|
// 分隔线
|
||||||
const separator = lineDiv.createDiv();
|
const separator = lineDiv.createDiv({ cls: 'toolbar-separator' });
|
||||||
separator.style.cssText = 'width: 1px; height: 24px; background: #dadce0; margin: 0 4px;';
|
|
||||||
|
|
||||||
const highlightStyle = lineDiv.createDiv({ cls: 'style-label' });
|
const highlightStyle = lineDiv.createDiv({ cls: 'style-label' });
|
||||||
highlightStyle.innerText = '代码高亮';
|
highlightStyle.innerText = '代码高亮';
|
||||||
highlightStyle.style.cssText = 'font-size: 13px; color: #5f6368; font-weight: 500; white-space: nowrap;';
|
|
||||||
|
|
||||||
const highlightStyleBtn = lineDiv.createEl('select', { cls: 'style-select' });
|
const highlightStyleBtn = lineDiv.createEl('select', { cls: 'style-select' });
|
||||||
highlightStyleBtn.style.cssText = '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: 120px;';
|
|
||||||
|
|
||||||
highlightStyleBtn.onchange = async () => {
|
highlightStyleBtn.onchange = async () => {
|
||||||
this.currentHighlight = highlightStyleBtn.value;
|
this.currentHighlight = highlightStyleBtn.value;
|
||||||
@@ -472,7 +433,6 @@ export class NotePreview extends ItemView {
|
|||||||
|
|
||||||
this.renderDiv = this.mainDiv.createDiv({cls: 'render-div'});
|
this.renderDiv = this.mainDiv.createDiv({cls: 'render-div'});
|
||||||
this.renderDiv.id = 'render-div';
|
this.renderDiv.id = 'render-div';
|
||||||
this.renderDiv.setAttribute('style', '-webkit-user-select: text; user-select: text;');
|
|
||||||
this.styleEl = this.renderDiv.createEl('style');
|
this.styleEl = this.renderDiv.createEl('style');
|
||||||
this.styleEl.setAttr('title', 'note-to-mp-style');
|
this.styleEl.setAttr('title', 'note-to-mp-style');
|
||||||
this.articleDiv = this.renderDiv.createEl('div');
|
this.articleDiv = this.renderDiv.createEl('div');
|
||||||
@@ -558,7 +518,7 @@ export class NotePreview extends ItemView {
|
|||||||
|
|
||||||
if (this.currentPlatform === 'xiaohongshu') {
|
if (this.currentPlatform === 'xiaohongshu') {
|
||||||
// 切换到小红书预览模式
|
// 切换到小红书预览模式
|
||||||
this.switchToXiaohongshuMode();
|
await this.switchToXiaohongshuMode();
|
||||||
} else {
|
} else {
|
||||||
// 切换到微信公众号模式
|
// 切换到微信公众号模式
|
||||||
this.switchToWechatMode();
|
this.switchToWechatMode();
|
||||||
@@ -568,7 +528,7 @@ export class NotePreview extends ItemView {
|
|||||||
/**
|
/**
|
||||||
* 切换到小红书预览模式
|
* 切换到小红书预览模式
|
||||||
*/
|
*/
|
||||||
private switchToXiaohongshuMode() {
|
private async switchToXiaohongshuMode() {
|
||||||
// 隐藏微信相关的工具栏行和平台选择器
|
// 隐藏微信相关的工具栏行和平台选择器
|
||||||
if (this.toolbar) {
|
if (this.toolbar) {
|
||||||
const wechatLines = this.toolbar.querySelectorAll('.wechat-only');
|
const wechatLines = this.toolbar.querySelectorAll('.wechat-only');
|
||||||
@@ -589,7 +549,6 @@ export class NotePreview extends ItemView {
|
|||||||
// 创建或显示小红书预览视图
|
// 创建或显示小红书预览视图
|
||||||
if (!this._xiaohongshuPreview) {
|
if (!this._xiaohongshuPreview) {
|
||||||
const xhsContainer = this.mainDiv.createDiv({ cls: 'xiaohongshu-preview-container' });
|
const xhsContainer = this.mainDiv.createDiv({ cls: 'xiaohongshu-preview-container' });
|
||||||
xhsContainer.style.cssText = 'width: 100%; height: 100%;';
|
|
||||||
this._xiaohongshuPreview = new XiaohongshuPreviewView(xhsContainer, this.app);
|
this._xiaohongshuPreview = new XiaohongshuPreviewView(xhsContainer, this.app);
|
||||||
|
|
||||||
// 设置回调函数
|
// 设置回调函数
|
||||||
@@ -613,8 +572,17 @@ export class NotePreview extends ItemView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 如果有当前文件,渲染小红书预览
|
// 如果有当前文件,渲染小红书预览
|
||||||
if (this.currentFile && this.articleHTML) {
|
if (this.currentFile) {
|
||||||
this._xiaohongshuPreview.renderArticle(this.articleHTML, this.currentFile);
|
// 如果还没有生成 articleHTML,先生成它
|
||||||
|
if (!this.articleHTML) {
|
||||||
|
await this.render.renderMarkdown(this.currentFile);
|
||||||
|
this.articleHTML = this.render.articleHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 渲染到小红书预览
|
||||||
|
if (this.articleHTML) {
|
||||||
|
await this._xiaohongshuPreview.renderArticle(this.articleHTML, this.currentFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -160,9 +160,8 @@ export class NoteToMpSettingTab extends PluginSettingTab {
|
|||||||
|
|
||||||
this.wxInfo = this.parseWXInfo();
|
this.wxInfo = this.parseWXInfo();
|
||||||
|
|
||||||
const helpEl = containerEl.createEl('div');
|
const helpEl = containerEl.createEl('div', { cls: 'setting-help-section' });
|
||||||
helpEl.style.cssText = 'display: flex;flex-direction: row;align-items: center;';
|
helpEl.createEl('h2', {text: '帮助文档', cls: 'setting-help-title'});
|
||||||
helpEl.createEl('h2', {text: '帮助文档'}).style.cssText = 'margin-right: 10px;';
|
|
||||||
helpEl.createEl('a', {text: 'https://sunboshi.tech/doc', attr: {href: 'https://sunboshi.tech/doc'}});
|
helpEl.createEl('a', {text: 'https://sunboshi.tech/doc', attr: {href: 'https://sunboshi.tech/doc'}});
|
||||||
|
|
||||||
containerEl.createEl('h2', {text: '插件设置'});
|
containerEl.createEl('h2', {text: '插件设置'});
|
||||||
|
|||||||
@@ -76,9 +76,7 @@ export class XiaohongshuWebAPI implements XiaohongshuAPI {
|
|||||||
private initializeWebview(): void {
|
private initializeWebview(): void {
|
||||||
// 创建隐藏的webview元素
|
// 创建隐藏的webview元素
|
||||||
this.webview = document.createElement('webview');
|
this.webview = document.createElement('webview');
|
||||||
this.webview.style.display = 'none';
|
this.webview.addClass('xhs-webview');
|
||||||
this.webview.style.width = '1200px';
|
|
||||||
this.webview.style.height = '800px';
|
|
||||||
|
|
||||||
// 设置webview属性
|
// 设置webview属性
|
||||||
this.webview.setAttribute('nodeintegration', 'false');
|
this.webview.setAttribute('nodeintegration', 'false');
|
||||||
|
|||||||
@@ -67,20 +67,16 @@ export class XiaohongshuLoginModal extends Modal {
|
|||||||
contentEl.empty();
|
contentEl.empty();
|
||||||
contentEl.addClass('xiaohongshu-login-modal');
|
contentEl.addClass('xiaohongshu-login-modal');
|
||||||
|
|
||||||
// 设置对话框样式
|
|
||||||
contentEl.style.width = '400px';
|
|
||||||
contentEl.style.padding = '20px';
|
|
||||||
|
|
||||||
// 标题
|
// 标题
|
||||||
contentEl.createEl('h2', {
|
contentEl.createEl('h2', {
|
||||||
text: '登录小红书',
|
text: '登录小红书',
|
||||||
attr: { style: 'text-align: center; margin-bottom: 20px; color: #ff4757;' }
|
cls: 'xhs-login-title'
|
||||||
});
|
});
|
||||||
|
|
||||||
// 说明文字
|
// 说明文字
|
||||||
const descEl = contentEl.createEl('p', {
|
const descEl = contentEl.createEl('p', {
|
||||||
text: '请使用手机号码和验证码登录小红书',
|
text: '请使用手机号码和验证码登录小红书',
|
||||||
attr: { style: 'text-align: center; color: #666; margin-bottom: 30px;' }
|
cls: 'xhs-login-desc'
|
||||||
});
|
});
|
||||||
|
|
||||||
// 手机号输入
|
// 手机号输入
|
||||||
@@ -97,23 +93,16 @@ export class XiaohongshuLoginModal extends Modal {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 设置输入框样式
|
// 设置输入框样式
|
||||||
text.inputEl.style.width = '100%';
|
text.inputEl.addClass('xhs-input-full');
|
||||||
text.inputEl.style.fontSize = '16px';
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 验证码输入和发送按钮
|
// 验证码输入和发送按钮
|
||||||
const codeContainer = contentEl.createDiv({ cls: 'code-container' });
|
const codeContainer = contentEl.createDiv({ cls: 'xhs-code-container' });
|
||||||
codeContainer.style.display = 'flex';
|
|
||||||
codeContainer.style.alignItems = 'center';
|
|
||||||
codeContainer.style.gap = '10px';
|
|
||||||
codeContainer.style.marginBottom = '20px';
|
|
||||||
|
|
||||||
const codeLabel = codeContainer.createDiv({ cls: 'setting-item-name' });
|
const codeLabel = codeContainer.createDiv({ cls: 'setting-item-name xhs-code-label' });
|
||||||
codeLabel.textContent = '验证码';
|
codeLabel.textContent = '验证码';
|
||||||
codeLabel.style.minWidth = '80px';
|
|
||||||
|
|
||||||
const codeInputWrapper = codeContainer.createDiv();
|
const codeInputWrapper = codeContainer.createDiv({ cls: 'xhs-code-input-wrapper' });
|
||||||
codeInputWrapper.style.flex = '1';
|
|
||||||
|
|
||||||
new Setting(codeInputWrapper)
|
new Setting(codeInputWrapper)
|
||||||
.addText(text => {
|
.addText(text => {
|
||||||
@@ -125,8 +114,7 @@ export class XiaohongshuLoginModal extends Modal {
|
|||||||
this.updateLoginButtonState();
|
this.updateLoginButtonState();
|
||||||
});
|
});
|
||||||
|
|
||||||
text.inputEl.style.width = '100%';
|
text.inputEl.addClass('xhs-input-full');
|
||||||
text.inputEl.style.fontSize = '16px';
|
|
||||||
text.inputEl.disabled = true; // 初始禁用
|
text.inputEl.disabled = true; // 初始禁用
|
||||||
|
|
||||||
// 回车键登录
|
// 回车键登录
|
||||||
@@ -142,22 +130,13 @@ export class XiaohongshuLoginModal extends Modal {
|
|||||||
.setButtonText('发送验证码')
|
.setButtonText('发送验证码')
|
||||||
.onClick(() => this.handleSendCode());
|
.onClick(() => this.handleSendCode());
|
||||||
|
|
||||||
this.sendCodeButton.buttonEl.style.minWidth = '120px';
|
this.sendCodeButton.buttonEl.addClass('xhs-send-code-btn');
|
||||||
this.sendCodeButton.buttonEl.style.marginLeft = '10px';
|
|
||||||
|
|
||||||
// 状态显示区域
|
// 状态显示区域
|
||||||
this.statusDiv = contentEl.createDiv({ cls: 'status-message' });
|
this.statusDiv = contentEl.createDiv({ cls: 'xhs-status-message' });
|
||||||
this.statusDiv.style.minHeight = '30px';
|
|
||||||
this.statusDiv.style.marginBottom = '20px';
|
|
||||||
this.statusDiv.style.textAlign = 'center';
|
|
||||||
this.statusDiv.style.fontSize = '14px';
|
|
||||||
|
|
||||||
// 按钮区域
|
// 按钮区域
|
||||||
const buttonContainer = contentEl.createDiv({ cls: 'button-container' });
|
const buttonContainer = contentEl.createDiv({ cls: 'xhs-button-container' });
|
||||||
buttonContainer.style.display = 'flex';
|
|
||||||
buttonContainer.style.justifyContent = 'center';
|
|
||||||
buttonContainer.style.gap = '15px';
|
|
||||||
buttonContainer.style.marginTop = '20px';
|
|
||||||
|
|
||||||
// 登录按钮
|
// 登录按钮
|
||||||
this.loginButton = new ButtonComponent(buttonContainer)
|
this.loginButton = new ButtonComponent(buttonContainer)
|
||||||
@@ -166,7 +145,7 @@ export class XiaohongshuLoginModal extends Modal {
|
|||||||
.setDisabled(true)
|
.setDisabled(true)
|
||||||
.onClick(() => this.handleLogin());
|
.onClick(() => this.handleLogin());
|
||||||
|
|
||||||
this.loginButton.buttonEl.style.minWidth = '100px';
|
this.loginButton.buttonEl.addClass('xhs-login-btn');
|
||||||
|
|
||||||
// 取消按钮
|
// 取消按钮
|
||||||
new ButtonComponent(buttonContainer)
|
new ButtonComponent(buttonContainer)
|
||||||
@@ -389,21 +368,7 @@ export class XiaohongshuLoginModal extends Modal {
|
|||||||
private showStatus(message: string, type: 'info' | 'success' | 'error' = 'info') {
|
private showStatus(message: string, type: 'info' | 'success' | 'error' = 'info') {
|
||||||
this.statusDiv.empty();
|
this.statusDiv.empty();
|
||||||
|
|
||||||
const messageEl = this.statusDiv.createSpan({ text: message });
|
const messageEl = this.statusDiv.createSpan({ text: message, cls: type || 'info' });
|
||||||
|
|
||||||
// 设置不同类型的样式
|
|
||||||
switch (type) {
|
|
||||||
case 'success':
|
|
||||||
messageEl.style.color = '#27ae60';
|
|
||||||
break;
|
|
||||||
case 'error':
|
|
||||||
messageEl.style.color = '#e74c3c';
|
|
||||||
break;
|
|
||||||
case 'info':
|
|
||||||
default:
|
|
||||||
messageEl.style.color = '#3498db';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onClose() {
|
onClose() {
|
||||||
|
|||||||
@@ -51,14 +51,13 @@ export class XiaohongshuPreviewView {
|
|||||||
*/
|
*/
|
||||||
build(): void {
|
build(): void {
|
||||||
this.container.empty();
|
this.container.empty();
|
||||||
this.container.style.cssText = 'display: flex; flex-direction: column; height: 100%; background: linear-gradient(135deg, #f5f7fa 0%, #e8eaf6 100%);';
|
this.container.addClass('xhs-preview-container');
|
||||||
|
|
||||||
// 顶部工具栏
|
// 顶部工具栏
|
||||||
this.buildTopToolbar();
|
this.buildTopToolbar();
|
||||||
|
|
||||||
// 页面容器
|
// 页面容器
|
||||||
this.pageContainer = this.container.createDiv({ cls: 'xhs-page-container' });
|
this.pageContainer = this.container.createDiv({ cls: 'xhs-page-container' });
|
||||||
this.pageContainer.style.cssText = 'flex: 1; overflow: auto; display: flex; justify-content: center; align-items: center; padding: 20px; background: radial-gradient(ellipse at top, rgba(255,255,255,0.1) 0%, transparent 70%);';
|
|
||||||
|
|
||||||
// 分页导航
|
// 分页导航
|
||||||
this.buildPageNavigation();
|
this.buildPageNavigation();
|
||||||
@@ -72,32 +71,22 @@ export class XiaohongshuPreviewView {
|
|||||||
*/
|
*/
|
||||||
private buildTopToolbar(): void {
|
private buildTopToolbar(): void {
|
||||||
this.topToolbar = this.container.createDiv({ cls: 'xhs-top-toolbar' });
|
this.topToolbar = this.container.createDiv({ cls: 'xhs-top-toolbar' });
|
||||||
this.topToolbar.style.cssText = 'display: flex; align-items: center; gap: 12px; padding: 8px 12px; background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%); border-bottom: 1px solid #e8eaed; box-shadow: 0 2px 4px rgba(0,0,0,0.04); flex-wrap: wrap;';
|
|
||||||
|
|
||||||
// 刷新按钮
|
// 刷新按钮
|
||||||
const refreshBtn = this.topToolbar.createEl('button', { text: '🔄 刷新' });
|
const refreshBtn = this.topToolbar.createEl('button', { text: '🔄 刷新', cls: 'toolbar-button purple-gradient' });
|
||||||
refreshBtn.style.cssText = 'padding: 6px 14px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); 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);';
|
|
||||||
refreshBtn.onmouseenter = () => refreshBtn.style.transform = 'translateY(-1px)';
|
|
||||||
refreshBtn.onmouseleave = () => refreshBtn.style.transform = 'translateY(0)';
|
|
||||||
refreshBtn.onclick = () => this.onRefresh();
|
refreshBtn.onclick = () => this.onRefresh();
|
||||||
|
|
||||||
// 发布按钮
|
// 发布按钮
|
||||||
const publishBtn = this.topToolbar.createEl('button', { text: '📤 发布' });
|
const publishBtn = this.topToolbar.createEl('button', { text: '📤 发布', cls: 'toolbar-button' });
|
||||||
publishBtn.style.cssText = 'padding: 6px 14px; background: linear-gradient(135deg, #1e88e5 0%, #1565c0 100%); 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);';
|
|
||||||
publishBtn.onmouseenter = () => publishBtn.style.transform = 'translateY(-1px)';
|
|
||||||
publishBtn.onmouseleave = () => publishBtn.style.transform = 'translateY(0)';
|
|
||||||
publishBtn.onclick = () => this.onPublish();
|
publishBtn.onclick = () => this.onPublish();
|
||||||
|
|
||||||
// 分隔线
|
// 分隔线
|
||||||
const separator2 = this.topToolbar.createDiv({ cls: 'toolbar-separator' });
|
const separator2 = this.topToolbar.createDiv({ cls: 'toolbar-separator' });
|
||||||
separator2.style.cssText = 'width: 1px; height: 24px; background: #dadce0; margin: 0 4px;';
|
|
||||||
|
|
||||||
// 模板选择
|
// 模板选择
|
||||||
const templateLabel = this.topToolbar.createDiv({ cls: 'toolbar-label' });
|
const templateLabel = this.topToolbar.createDiv({ cls: 'toolbar-label' });
|
||||||
templateLabel.innerText = '模板';
|
templateLabel.innerText = '模板';
|
||||||
templateLabel.style.cssText = 'font-size: 11px; color: #5f6368; font-weight: 500; white-space: nowrap;';
|
this.templateSelect = this.topToolbar.createEl('select', { cls: 'xhs-select' });
|
||||||
this.templateSelect = this.topToolbar.createEl('select');
|
|
||||||
this.templateSelect.style.cssText = 'padding: 4px 8px; border: 1px solid #dadce0; border-radius: 4px; background: white; font-size: 11px; cursor: pointer; transition: border-color 0.2s ease;';
|
|
||||||
['默认模板', '简约模板', '杂志模板'].forEach(name => {
|
['默认模板', '简约模板', '杂志模板'].forEach(name => {
|
||||||
const option = this.templateSelect.createEl('option');
|
const option = this.templateSelect.createEl('option');
|
||||||
option.value = name;
|
option.value = name;
|
||||||
@@ -107,9 +96,7 @@ export class XiaohongshuPreviewView {
|
|||||||
// 主题选择
|
// 主题选择
|
||||||
const themeLabel = this.topToolbar.createDiv({ cls: 'toolbar-label' });
|
const themeLabel = this.topToolbar.createDiv({ cls: 'toolbar-label' });
|
||||||
themeLabel.innerText = '主题';
|
themeLabel.innerText = '主题';
|
||||||
themeLabel.style.cssText = 'font-size: 11px; color: #5f6368; font-weight: 500; white-space: nowrap;';
|
this.themeSelect = this.topToolbar.createEl('select', { cls: 'xhs-select' });
|
||||||
this.themeSelect = this.topToolbar.createEl('select');
|
|
||||||
this.themeSelect.style.cssText = 'padding: 4px 8px; border: 1px solid #dadce0; border-radius: 4px; background: white; font-size: 11px; cursor: pointer; transition: border-color 0.2s ease;';
|
|
||||||
const themes = this.assetsManager.themes;
|
const themes = this.assetsManager.themes;
|
||||||
themes.forEach(theme => {
|
themes.forEach(theme => {
|
||||||
const option = this.themeSelect.createEl('option');
|
const option = this.themeSelect.createEl('option');
|
||||||
@@ -122,9 +109,7 @@ export class XiaohongshuPreviewView {
|
|||||||
// 字体选择
|
// 字体选择
|
||||||
const fontLabel = this.topToolbar.createDiv({ cls: 'toolbar-label' });
|
const fontLabel = this.topToolbar.createDiv({ cls: 'toolbar-label' });
|
||||||
fontLabel.innerText = '字体';
|
fontLabel.innerText = '字体';
|
||||||
fontLabel.style.cssText = 'font-size: 11px; color: #5f6368; font-weight: 500; white-space: nowrap;';
|
this.fontSelect = this.topToolbar.createEl('select', { cls: 'xhs-select' });
|
||||||
this.fontSelect = this.topToolbar.createEl('select');
|
|
||||||
this.fontSelect.style.cssText = 'padding: 4px 8px; border: 1px solid #dadce0; border-radius: 4px; background: white; font-size: 11px; cursor: pointer; transition: border-color 0.2s ease;';
|
|
||||||
['系统默认', '宋体', '黑体', '楷体', '仿宋'].forEach(name => {
|
['系统默认', '宋体', '黑体', '楷体', '仿宋'].forEach(name => {
|
||||||
const option = this.fontSelect.createEl('option');
|
const option = this.fontSelect.createEl('option');
|
||||||
option.value = name;
|
option.value = name;
|
||||||
@@ -135,23 +120,14 @@ export class XiaohongshuPreviewView {
|
|||||||
// 字号控制
|
// 字号控制
|
||||||
const fontSizeLabel = this.topToolbar.createDiv({ cls: 'toolbar-label' });
|
const fontSizeLabel = this.topToolbar.createDiv({ cls: 'toolbar-label' });
|
||||||
fontSizeLabel.innerText = '字号';
|
fontSizeLabel.innerText = '字号';
|
||||||
fontSizeLabel.style.cssText = 'font-size: 11px; color: #5f6368; font-weight: 500; white-space: nowrap;';
|
|
||||||
const fontSizeGroup = this.topToolbar.createDiv({ cls: 'font-size-group' });
|
const fontSizeGroup = this.topToolbar.createDiv({ cls: 'font-size-group' });
|
||||||
fontSizeGroup.style.cssText = 'display: flex; align-items: center; gap: 6px; background: white; border: 1px solid #dadce0; border-radius: 4px; padding: 2px;';
|
|
||||||
|
|
||||||
const decreaseBtn = fontSizeGroup.createEl('button', { text: '−' });
|
const decreaseBtn = fontSizeGroup.createEl('button', { text: '−', cls: 'font-size-btn' });
|
||||||
decreaseBtn.style.cssText = 'width: 24px; height: 24px; border: none; background: transparent; border-radius: 3px; cursor: pointer; font-size: 16px; color: #5f6368; transition: background 0.2s ease;';
|
|
||||||
decreaseBtn.onmouseenter = () => decreaseBtn.style.background = '#f1f3f4';
|
|
||||||
decreaseBtn.onmouseleave = () => decreaseBtn.style.background = 'transparent';
|
|
||||||
decreaseBtn.onclick = () => this.changeFontSize(-1);
|
decreaseBtn.onclick = () => this.changeFontSize(-1);
|
||||||
|
|
||||||
this.fontSizeDisplay = fontSizeGroup.createEl('span', { text: '16' });
|
this.fontSizeDisplay = fontSizeGroup.createEl('span', { text: '16', cls: 'font-size-display' });
|
||||||
this.fontSizeDisplay.style.cssText = 'min-width: 24px; text-align: center; font-size: 12px; color: #202124; font-weight: 500;';
|
|
||||||
|
|
||||||
const increaseBtn = fontSizeGroup.createEl('button', { text: '+' });
|
const increaseBtn = fontSizeGroup.createEl('button', { text: '+', cls: 'font-size-btn' });
|
||||||
increaseBtn.style.cssText = 'width: 24px; height: 24px; border: none; background: transparent; border-radius: 3px; cursor: pointer; font-size: 14px; color: #5f6368; transition: background 0.2s ease;';
|
|
||||||
increaseBtn.onmouseenter = () => increaseBtn.style.background = '#f1f3f4';
|
|
||||||
increaseBtn.onmouseleave = () => increaseBtn.style.background = 'transparent';
|
|
||||||
increaseBtn.onclick = () => this.changeFontSize(1);
|
increaseBtn.onclick = () => this.changeFontSize(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,37 +136,13 @@ export class XiaohongshuPreviewView {
|
|||||||
*/
|
*/
|
||||||
private buildPageNavigation(): void {
|
private buildPageNavigation(): void {
|
||||||
this.pageNavigation = this.container.createDiv({ cls: 'xhs-page-navigation' });
|
this.pageNavigation = this.container.createDiv({ cls: 'xhs-page-navigation' });
|
||||||
this.pageNavigation.style.cssText = 'display: flex; justify-content: center; align-items: center; gap: 16px; padding: 12px; background: white; border-bottom: 1px solid #e8eaed;';
|
|
||||||
|
|
||||||
const prevBtn = this.pageNavigation.createEl('button', { text: '‹' });
|
const prevBtn = this.pageNavigation.createEl('button', { text: '‹', cls: 'xhs-nav-btn' });
|
||||||
prevBtn.style.cssText = 'width: 36px; height: 36px; border: 1px solid #dadce0; 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);';
|
|
||||||
prevBtn.onmouseenter = () => {
|
|
||||||
prevBtn.style.background = 'linear-gradient(135deg, #1e88e5 0%, #1565c0 100%)';
|
|
||||||
prevBtn.style.color = 'white';
|
|
||||||
prevBtn.style.borderColor = '#1e88e5';
|
|
||||||
};
|
|
||||||
prevBtn.onmouseleave = () => {
|
|
||||||
prevBtn.style.background = 'white';
|
|
||||||
prevBtn.style.color = '#5f6368';
|
|
||||||
prevBtn.style.borderColor = '#dadce0';
|
|
||||||
};
|
|
||||||
prevBtn.onclick = () => this.previousPage();
|
prevBtn.onclick = () => this.previousPage();
|
||||||
|
|
||||||
this.pageNumberDisplay = this.pageNavigation.createEl('span', { text: '1/1' });
|
this.pageNumberDisplay = this.pageNavigation.createEl('span', { text: '1/1', cls: 'xhs-page-number' });
|
||||||
this.pageNumberDisplay.style.cssText = 'font-size: 14px; min-width: 50px; text-align: center; color: #202124; font-weight: 500;';
|
|
||||||
|
|
||||||
const nextBtn = this.pageNavigation.createEl('button', { text: '›' });
|
const nextBtn = this.pageNavigation.createEl('button', { text: '›', cls: 'xhs-nav-btn' });
|
||||||
nextBtn.style.cssText = 'width: 36px; height: 36px; border: 1px solid #dadce0; 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);';
|
|
||||||
nextBtn.onmouseenter = () => {
|
|
||||||
nextBtn.style.background = 'linear-gradient(135deg, #1e88e5 0%, #1565c0 100%)';
|
|
||||||
nextBtn.style.color = 'white';
|
|
||||||
nextBtn.style.borderColor = '#1e88e5';
|
|
||||||
};
|
|
||||||
nextBtn.onmouseleave = () => {
|
|
||||||
nextBtn.style.background = 'white';
|
|
||||||
nextBtn.style.color = '#5f6368';
|
|
||||||
nextBtn.style.borderColor = '#dadce0';
|
|
||||||
};
|
|
||||||
nextBtn.onclick = () => this.nextPage();
|
nextBtn.onclick = () => this.nextPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,30 +151,11 @@ export class XiaohongshuPreviewView {
|
|||||||
*/
|
*/
|
||||||
private buildBottomToolbar(): void {
|
private buildBottomToolbar(): void {
|
||||||
this.bottomToolbar = this.container.createDiv({ cls: 'xhs-bottom-toolbar' });
|
this.bottomToolbar = this.container.createDiv({ cls: 'xhs-bottom-toolbar' });
|
||||||
this.bottomToolbar.style.cssText = 'display: flex; justify-content: center; gap: 12px; padding: 12px 16px; background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%); border-top: 1px solid #e8eaed; box-shadow: 0 -2px 4px rgba(0,0,0,0.04);';
|
|
||||||
|
|
||||||
const currentPageBtn = this.bottomToolbar.createEl('button', { text: '⬇ 当前页切图' });
|
const currentPageBtn = this.bottomToolbar.createEl('button', { text: '⬇ 当前页切图', cls: 'xhs-slice-btn' });
|
||||||
currentPageBtn.style.cssText = 'padding: 8px 20px; background: linear-gradient(135deg, #1e88e5 0%, #1565c0 100%); 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);';
|
|
||||||
currentPageBtn.onmouseenter = () => {
|
|
||||||
currentPageBtn.style.transform = 'translateY(-2px)';
|
|
||||||
currentPageBtn.style.boxShadow = '0 4px 12px rgba(30, 136, 229, 0.4)';
|
|
||||||
};
|
|
||||||
currentPageBtn.onmouseleave = () => {
|
|
||||||
currentPageBtn.style.transform = 'translateY(0)';
|
|
||||||
currentPageBtn.style.boxShadow = '0 2px 6px rgba(30, 136, 229, 0.3)';
|
|
||||||
};
|
|
||||||
currentPageBtn.onclick = () => this.sliceCurrentPage();
|
currentPageBtn.onclick = () => this.sliceCurrentPage();
|
||||||
|
|
||||||
const allPagesBtn = this.bottomToolbar.createEl('button', { text: '⇓ 全部页切图' });
|
const allPagesBtn = this.bottomToolbar.createEl('button', { text: '⇓ 全部页切图', cls: 'xhs-slice-btn secondary' });
|
||||||
allPagesBtn.style.cssText = 'padding: 8px 20px; background: linear-gradient(135deg, #42a5f5 0%, #1e88e5 100%); 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(66, 165, 245, 0.3);';
|
|
||||||
allPagesBtn.onmouseenter = () => {
|
|
||||||
allPagesBtn.style.transform = 'translateY(-2px)';
|
|
||||||
allPagesBtn.style.boxShadow = '0 4px 12px rgba(66, 165, 245, 0.4)';
|
|
||||||
};
|
|
||||||
allPagesBtn.onmouseleave = () => {
|
|
||||||
allPagesBtn.style.transform = 'translateY(0)';
|
|
||||||
allPagesBtn.style.boxShadow = '0 2px 6px rgba(66, 165, 245, 0.3)';
|
|
||||||
};
|
|
||||||
allPagesBtn.onclick = () => this.sliceAllPages();
|
allPagesBtn.onclick = () => this.sliceAllPages();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,7 +171,7 @@ export class XiaohongshuPreviewView {
|
|||||||
// 创建临时容器用于分页
|
// 创建临时容器用于分页
|
||||||
const tempContainer = document.createElement('div');
|
const tempContainer = document.createElement('div');
|
||||||
tempContainer.innerHTML = articleHTML;
|
tempContainer.innerHTML = articleHTML;
|
||||||
tempContainer.style.cssText = `width: ${this.settings.sliceImageWidth}px;`;
|
tempContainer.style.width = `${this.settings.sliceImageWidth}px`;
|
||||||
document.body.appendChild(tempContainer);
|
document.body.appendChild(tempContainer);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
418
styles.css
@@ -16,6 +16,8 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
-webkit-user-select: text;
|
||||||
|
user-select: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-toolbar {
|
.preview-toolbar {
|
||||||
@@ -246,3 +248,419 @@ label:hover {
|
|||||||
transform: rotate(360deg);
|
transform: rotate(360deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* =========================================================== */
|
||||||
|
/* Toolbar 行样式 */
|
||||||
|
/* =========================================================== */
|
||||||
|
|
||||||
|
.toolbar-line {
|
||||||
|
display: flex;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-line.flex-wrap {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.platform-selector-line {
|
||||||
|
background: linear-gradient(135deg, #fff3e0 0%, #ffffff 100%) !important;
|
||||||
|
border-left: 4px solid #1e88e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================== */
|
||||||
|
/* 平台选择器样式 */
|
||||||
|
/* =========================================================== */
|
||||||
|
|
||||||
|
.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%);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-button:hover {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 4px 8px rgba(30, 136, 229, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-button.purple-gradient {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
box-shadow: 0 2px 6px rgba(102, 126, 234, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-button.purple-gradient:hover {
|
||||||
|
box-shadow: 0 4px 8px rgba(102, 126, 234, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================== */
|
||||||
|
/* 分隔线样式 */
|
||||||
|
/* =========================================================== */
|
||||||
|
|
||||||
|
.toolbar-separator {
|
||||||
|
width: 1px;
|
||||||
|
height: 24px;
|
||||||
|
background: #dadce0;
|
||||||
|
margin: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================== */
|
||||||
|
/* Doc Modal 样式 */
|
||||||
|
/* =========================================================== */
|
||||||
|
|
||||||
|
.doc-modal {
|
||||||
|
width: 640px;
|
||||||
|
height: 720px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.doc-modal-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.doc-modal-title {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.doc-modal-desc {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
-webkit-user-select: text;
|
||||||
|
user-select: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.doc-modal-iframe {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================== */
|
||||||
|
/* Setting Tab 帮助文档样式 */
|
||||||
|
/* =========================================================== */
|
||||||
|
|
||||||
|
.setting-help-section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-help-title {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================== */
|
||||||
|
/* Xiaohongshu WebView 样式 */
|
||||||
|
/* =========================================================== */
|
||||||
|
|
||||||
|
.xhs-webview {
|
||||||
|
display: none;
|
||||||
|
width: 1200px;
|
||||||
|
height: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================== */
|
||||||
|
/* Xiaohongshu Preview View 样式 */
|
||||||
|
/* =========================================================== */
|
||||||
|
|
||||||
|
.xiaohongshu-preview-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-preview-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(135deg, #f5f7fa 0%, #e8eaf6 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-page-container {
|
||||||
|
flex: 1;
|
||||||
|
overflow: auto;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 20px;
|
||||||
|
background: radial-gradient(ellipse at top, rgba(255,255,255,0.1) 0%, transparent 70%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-top-toolbar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
|
||||||
|
border-bottom: 1px solid #e8eaed;
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.04);
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-label {
|
||||||
|
font-size: 11px;
|
||||||
|
color: #5f6368;
|
||||||
|
font-weight: 500;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-select {
|
||||||
|
padding: 4px 8px;
|
||||||
|
border: 1px solid #dadce0;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: white;
|
||||||
|
font-size: 11px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: border-color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-select:hover {
|
||||||
|
border-color: #1e88e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-select:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #1e88e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-size-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
background: white;
|
||||||
|
border: 1px solid #dadce0;
|
||||||
|
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: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
padding: 12px;
|
||||||
|
background: white;
|
||||||
|
border-bottom: 1px solid #e8eaed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-nav-btn {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border: 1px solid #dadce0;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-nav-btn:hover {
|
||||||
|
background: linear-gradient(135deg, #1e88e5 0%, #1565c0 100%);
|
||||||
|
color: white;
|
||||||
|
border-color: #1e88e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-page-number {
|
||||||
|
font-size: 14px;
|
||||||
|
min-width: 50px;
|
||||||
|
text-align: center;
|
||||||
|
color: #202124;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-bottom-toolbar {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 12px 16px;
|
||||||
|
background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
|
||||||
|
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%);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-slice-btn:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(30, 136, 229, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-slice-btn.secondary {
|
||||||
|
background: linear-gradient(135deg, #42a5f5 0%, #1e88e5 100%);
|
||||||
|
box-shadow: 0 2px 6px rgba(66, 165, 245, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-slice-btn.secondary:hover {
|
||||||
|
box-shadow: 0 4px 12px rgba(66, 165, 245, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================== */
|
||||||
|
/* Xiaohongshu Login Modal 样式 */
|
||||||
|
/* =========================================================== */
|
||||||
|
|
||||||
|
.xiaohongshu-login-modal {
|
||||||
|
width: 400px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-login-title {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: #ff4757;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-login-desc {
|
||||||
|
text-align: center;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-code-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-code-label {
|
||||||
|
min-width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-code-input-wrapper {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-input-full {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-send-code-btn {
|
||||||
|
min-width: 120px;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-status-message {
|
||||||
|
min-height: 30px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-status-message.success {
|
||||||
|
color: #27ae60;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-status-message.error {
|
||||||
|
color: #e74c3c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-status-message.info {
|
||||||
|
color: #3498db;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-button-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 15px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-login-btn {
|
||||||
|
min-width: 100px;
|
||||||
|
}
|
||||||
23
todolist.md
@@ -42,8 +42,10 @@
|
|||||||
+------------------------------------------------------------+
|
+------------------------------------------------------------+
|
||||||
| [⬇ 当前页切图] [⇓ 全部页切图] | ← 底部操作栏
|
| [⬇ 当前页切图] [⇓ 全部页切图] | ← 底部操作栏
|
||||||
+------------------------------------------------------------+
|
+------------------------------------------------------------+
|
||||||
|
✅
|
||||||
|
|
||||||
效果参考附图。
|
效果参考附图。
|
||||||
|
✅
|
||||||
|
|
||||||
- 先对html分页,在预览中分页显示。
|
- 先对html分页,在预览中分页显示。
|
||||||
- 页面适配切图比例的设置。
|
- 页面适配切图比例的设置。
|
||||||
@@ -52,12 +54,27 @@
|
|||||||
- 点击"+"所有字体加一号,点击"-"所有字体减一号。
|
- 点击"+"所有字体加一号,点击"-"所有字体减一号。
|
||||||
- 点击"当前页切图",把当前html页面转为png图片,图片保存路径和命名按此前设置。
|
- 点击"当前页切图",把当前html页面转为png图片,图片保存路径和命名按此前设置。
|
||||||
- 点击"全部页切图",把所有html页面转为png图片,图片保存路径和命名按此前设置。
|
- 点击"全部页切图",把所有html页面转为png图片,图片保存路径和命名按此前设置。
|
||||||
|
✅
|
||||||
|
|
||||||
## 问题
|
## 问题
|
||||||
1. "发布平台"选“小红书”时,预览页面没有加载当前文章。
|
1. "发布平台"首次选“小红书”时,预览页面没有加载当前文章。
|
||||||
|
✅
|
||||||
2. 顶部按钮适应窗口宽度,超出窗口,折行显示。
|
2. 顶部按钮适应窗口宽度,超出窗口,折行显示。
|
||||||
3. 页预览不完整,改为
|
✅
|
||||||
|
3. 小红书模式,页预览不完整
|
||||||
|
|
||||||
|
4. 修改:
|
||||||
|
- 公共部分独立出来,如“发布平台”,放在新建platform-choose.ts中,“发布平台”选择切换平台逻辑放在该模块中,便于以后其他平台扩展。
|
||||||
|
- 其他所有组件独立。node-preview.ts改为mp-preview.ts, 专门用于处理微信公众号模式下的页面和逻辑处理;preview-view.ts改为xhs-preview.ts,专门用于小红书模式下的页面和逻辑处理。
|
||||||
|
|
||||||
|
效果不理想。❌,需求修改如下:
|
||||||
|
|
||||||
|
目前mp-preview.ts中既实现微信公众号(micro-public,mp)的处理逻辑,又实现小红书(xiaohongshu,xhs)的处理逻辑。优化:
|
||||||
|
- 平台选择的逻辑放在platform-choose.ts中。
|
||||||
|
平台选择后,依据选择模式,调用mp-preview.ts(微信公众号mp)或xhs-preview.ts(小红书,xhs)中的方法。
|
||||||
|
- mp-preview.ts中保留微信公众号模式(micro-public,mp)相关的处理逻辑。
|
||||||
|
- mp-preview.ts中去掉小红书处理逻辑(移到xhs-preview.ts中)。
|
||||||
|
5. 把代码逻辑中的所有css移到styles.css中。✅
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||