update at 2025-10-08 09:18:20
This commit is contained in:
@@ -1,28 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2024-2025 Sun Booshi
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
/**
|
||||
* 文件:batch-publish-modal.ts
|
||||
* 功能:批量发布模态窗口;支持文件夹 / 多文件选择 + 多平台勾选。
|
||||
* - 文件列表与过滤
|
||||
* - 平台选择(公众号 / 小红书)
|
||||
* - 批量触发发布逻辑
|
||||
*/
|
||||
|
||||
import { App, Modal, Setting, TFile, Notice, ButtonComponent } from 'obsidian';
|
||||
import { BatchArticleFilter, BatchFilterConfig } from './batch-filter';
|
||||
import NoteToMpPlugin from './main';
|
||||
// 小红书功能模块
|
||||
import { XiaohongshuContentAdapter } from './xiaohongshu/adapter';
|
||||
import { XiaohongshuAPIManager } from './xiaohongshu/api';
|
||||
|
||||
/**
|
||||
* BatchPublishModal
|
||||
@@ -55,6 +44,11 @@ export class BatchPublishModal extends Modal {
|
||||
private resultsContainer: HTMLElement;
|
||||
private publishButton: ButtonComponent;
|
||||
|
||||
// 平台选择相关(新增)
|
||||
private wechatCheckbox: HTMLInputElement;
|
||||
private xiaohongshuCheckbox: HTMLInputElement;
|
||||
private allPlatformsCheckbox: HTMLInputElement;
|
||||
|
||||
// 鼠标框选相关
|
||||
private isSelecting = false;
|
||||
private selectionStart: { x: number; y: number } | null = null;
|
||||
@@ -114,6 +108,61 @@ export class BatchPublishModal extends Modal {
|
||||
buttonContainer.style.borderTop = '1px solid var(--background-modifier-border)';
|
||||
buttonContainer.style.flexShrink = '0';
|
||||
|
||||
// 发布平台选择(新增)
|
||||
const platformContainer = buttonContainer.createDiv('platform-select-container');
|
||||
platformContainer.style.marginBottom = '15px';
|
||||
platformContainer.style.display = 'flex';
|
||||
platformContainer.style.alignItems = 'center';
|
||||
platformContainer.style.justifyContent = 'center';
|
||||
platformContainer.style.gap = '10px';
|
||||
|
||||
const platformLabel = platformContainer.createSpan();
|
||||
platformLabel.innerText = '发布到: ';
|
||||
|
||||
const wechatCheckbox = platformContainer.createEl('input', { type: 'checkbox' });
|
||||
wechatCheckbox.id = 'publish-wechat';
|
||||
wechatCheckbox.checked = true;
|
||||
this.wechatCheckbox = wechatCheckbox;
|
||||
const wechatLabel = platformContainer.createEl('label');
|
||||
wechatLabel.setAttribute('for', 'publish-wechat');
|
||||
wechatLabel.innerText = '微信公众号';
|
||||
wechatLabel.style.marginRight = '15px';
|
||||
|
||||
const xiaohongshuCheckbox = platformContainer.createEl('input', { type: 'checkbox' });
|
||||
xiaohongshuCheckbox.id = 'publish-xiaohongshu';
|
||||
this.xiaohongshuCheckbox = xiaohongshuCheckbox;
|
||||
const xiaohongshuLabel = platformContainer.createEl('label');
|
||||
xiaohongshuLabel.setAttribute('for', 'publish-xiaohongshu');
|
||||
xiaohongshuLabel.innerText = '小红书';
|
||||
xiaohongshuLabel.style.marginRight = '15px';
|
||||
|
||||
const allPlatformsCheckbox = platformContainer.createEl('input', { type: 'checkbox' });
|
||||
allPlatformsCheckbox.id = 'publish-all';
|
||||
this.allPlatformsCheckbox = allPlatformsCheckbox;
|
||||
const allPlatformsLabel = platformContainer.createEl('label');
|
||||
allPlatformsLabel.setAttribute('for', 'publish-all');
|
||||
allPlatformsLabel.innerText = '全部平台';
|
||||
|
||||
// 全部平台checkbox的联动逻辑
|
||||
allPlatformsCheckbox.addEventListener('change', () => {
|
||||
if (allPlatformsCheckbox.checked) {
|
||||
wechatCheckbox.checked = true;
|
||||
xiaohongshuCheckbox.checked = true;
|
||||
}
|
||||
});
|
||||
|
||||
// 单个平台checkbox的联动逻辑
|
||||
const updateAllPlatforms = () => {
|
||||
if (wechatCheckbox.checked && xiaohongshuCheckbox.checked) {
|
||||
allPlatformsCheckbox.checked = true;
|
||||
} else {
|
||||
allPlatformsCheckbox.checked = false;
|
||||
}
|
||||
};
|
||||
|
||||
wechatCheckbox.addEventListener('change', updateAllPlatforms);
|
||||
xiaohongshuCheckbox.addEventListener('change', updateAllPlatforms);
|
||||
|
||||
new ButtonComponent(buttonContainer)
|
||||
.setButtonText('应用筛选')
|
||||
.setCta()
|
||||
@@ -406,56 +455,135 @@ export class BatchPublishModal extends Modal {
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取选择的发布平台
|
||||
const platforms = this.getSelectedPlatforms();
|
||||
if (platforms.length === 0) {
|
||||
new Notice('请选择至少一个发布平台');
|
||||
return;
|
||||
}
|
||||
|
||||
const files = Array.from(this.selectedFiles);
|
||||
const total = files.length;
|
||||
const totalTasks = files.length * platforms.length;
|
||||
let completed = 0;
|
||||
let failed = 0;
|
||||
|
||||
// 显示进度
|
||||
const notice = new Notice(`开始批量发布 ${total} 篇文章...`, 0);
|
||||
const notice = new Notice(`开始批量发布 ${files.length} 篇文章到 ${platforms.join('、')}...`, 0);
|
||||
|
||||
try {
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const file = files[i];
|
||||
|
||||
try {
|
||||
// 更新进度
|
||||
notice.setMessage(`正在发布: ${file.basename} (${i + 1}/${total})`);
|
||||
|
||||
// 激活预览视图并发布
|
||||
await this.plugin.activateView();
|
||||
const preview = this.plugin.getNotePreview();
|
||||
if (preview) {
|
||||
await preview.renderMarkdown(file);
|
||||
await preview.postArticle();
|
||||
for (const platform of platforms) {
|
||||
try {
|
||||
// 更新进度
|
||||
const taskIndex = i * platforms.length + platforms.indexOf(platform) + 1;
|
||||
notice.setMessage(`正在发布: ${file.basename} 到 ${platform} (${taskIndex}/${totalTasks})`);
|
||||
|
||||
if (platform === '微信公众号') {
|
||||
await this.publishToWechat(file);
|
||||
} else if (platform === '小红书') {
|
||||
await this.publishToXiaohongshu(file);
|
||||
}
|
||||
|
||||
completed++;
|
||||
} else {
|
||||
throw new Error('无法获取预览视图');
|
||||
|
||||
} catch (error) {
|
||||
console.error(`发布文章 ${file.basename} 到 ${platform} 失败:`, error);
|
||||
failed++;
|
||||
}
|
||||
|
||||
// 避免请求过于频繁
|
||||
if (i < files.length - 1) {
|
||||
const taskIndex = i * platforms.length + platforms.indexOf(platform) + 1;
|
||||
if (taskIndex < totalTasks) {
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error(`发布文章 ${file.basename} 失败:`, error);
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
|
||||
// 显示最终结果
|
||||
notice.hide();
|
||||
new Notice(`批量发布完成!成功: ${completed} 篇,失败: ${failed} 篇`);
|
||||
new Notice(`批量发布完成!成功: ${completed} 个任务,失败: ${failed} 个任务`);
|
||||
|
||||
if (completed > 0) {
|
||||
this.close();
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
notice.hide();
|
||||
new Notice('批量发布过程中出错: ' + error.message);
|
||||
console.error(error);
|
||||
new Notice('批量发布过程中发生错误: ' + error.message);
|
||||
console.error('批量发布错误:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取选择的发布平台
|
||||
*/
|
||||
private getSelectedPlatforms(): string[] {
|
||||
const platforms: string[] = [];
|
||||
|
||||
if (this.wechatCheckbox.checked) {
|
||||
platforms.push('微信公众号');
|
||||
}
|
||||
|
||||
if (this.xiaohongshuCheckbox.checked) {
|
||||
platforms.push('小红书');
|
||||
}
|
||||
|
||||
return platforms;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布到微信公众号
|
||||
*/
|
||||
private async publishToWechat(file: TFile): Promise<void> {
|
||||
// 激活预览视图并发布
|
||||
await this.plugin.activateView();
|
||||
const preview = this.plugin.getNotePreview();
|
||||
if (preview) {
|
||||
// 确保预览器处于微信模式
|
||||
preview.currentPlatform = 'wechat';
|
||||
await preview.renderMarkdown(file);
|
||||
await preview.postToWechat();
|
||||
} else {
|
||||
throw new Error('无法获取预览视图');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布到小红书
|
||||
*/
|
||||
private async publishToXiaohongshu(file: TFile): Promise<void> {
|
||||
try {
|
||||
// 读取文件内容
|
||||
const fileContent = await this.app.vault.read(file);
|
||||
|
||||
// 使用小红书适配器转换内容
|
||||
const adapter = new XiaohongshuContentAdapter();
|
||||
const xiaohongshuPost = adapter.adaptMarkdownToXiaohongshu(fileContent, {
|
||||
addStyle: true,
|
||||
generateTitle: true
|
||||
});
|
||||
|
||||
// 验证内容
|
||||
const validation = adapter.validatePost(xiaohongshuPost);
|
||||
if (!validation.valid) {
|
||||
throw new Error('内容验证失败: ' + validation.errors.join('; '));
|
||||
}
|
||||
|
||||
// 获取小红书API实例
|
||||
const api = XiaohongshuAPIManager.getInstance(false);
|
||||
|
||||
// 检查登录状态
|
||||
const isLoggedIn = await api.checkLoginStatus();
|
||||
if (!isLoggedIn) {
|
||||
throw new Error('小红书未登录,请在预览界面登录后再试');
|
||||
}
|
||||
|
||||
// 发布内容
|
||||
const result = await api.createPost(xiaohongshuPost);
|
||||
|
||||
if (!result.success) {
|
||||
throw new Error(result.message);
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`发布到小红书失败: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user