update at 2025-10-08 19:45:28

This commit is contained in:
douboer
2025-10-08 19:45:28 +08:00
parent 5d32c0f5e7
commit 3460669602
20 changed files with 3325 additions and 101 deletions

378
src/preview-manager.ts Normal file
View File

@@ -0,0 +1,378 @@
/**
* 文件preview-manager.ts
* 作用:预览管理器,负责协调所有平台预览组件
*
* 职责:
* 1. 创建和管理所有子组件platform-chooser, wechat-preview, xhs-preview
* 2. 处理平台切换逻辑(唯一入口)
* 3. 管理文章渲染和状态同步
* 4. 提供统一的对外接口
*
* 设计模式:
* - 中介者模式Mediator: 协调各组件交互
* - 外观模式Facade: 提供简单的对外接口
*/
import { TFile, Notice, App } from 'obsidian';
import { PlatformChooser, PlatformType } from './platform-chooser';
import { WechatPreview } from './wechat/wechat-preview';
import { XiaohongshuPreview } from './xiaohongshu/xhs-preview';
import { ArticleRender } from './article-render';
import { NMPSettings } from './settings';
export class PreviewManager {
private container: HTMLElement;
private app: App;
private render: ArticleRender;
private settings: NMPSettings;
// 子组件
private platformChooser: PlatformChooser | null = null;
private wechatPreview: WechatPreview | null = null;
private xhsPreview: XiaohongshuPreview | null = null;
// UI 容器
private mainDiv: HTMLDivElement | null = null;
private wechatContainer: HTMLDivElement | null = null;
private xhsContainer: HTMLDivElement | null = null;
// 状态
private currentPlatform: PlatformType = 'wechat';
private currentFile: TFile | null = null;
constructor(container: HTMLElement, app: App, render: ArticleRender) {
this.container = container;
this.app = app;
this.render = render;
this.settings = NMPSettings.getInstance();
}
/**
* 构建界面(主入口)
*/
async build(): Promise<void> {
console.log('[PreviewManager] 开始构建界面');
// 清空容器
this.container.empty();
// 创建主容器
this.mainDiv = this.container.createDiv({ cls: 'note-preview' });
// 1. 创建并构建平台选择器
this.createPlatformChooser();
// 2. 创建并构建微信预览
this.createWechatPreview();
// 3. 创建并构建小红书预览
this.createXiaohongshuPreview();
// 4. 初始显示微信平台
await this.switchPlatform('wechat');
console.log('[PreviewManager] 界面构建完成');
}
/**
* 创建平台选择器
*/
private createPlatformChooser(): void {
if (!this.mainDiv) return;
// 创建平台选择器容器
const chooserContainer = this.mainDiv.createDiv({ cls: 'platform-chooser-container' });
// 创建平台选择器实例
this.platformChooser = new PlatformChooser(chooserContainer);
// 设置平台切换回调
this.platformChooser.setOnChange((platform) => {
this.switchPlatform(platform as PlatformType);
});
// 构建 UI
this.platformChooser.render();
}
/**
* 创建微信预览组件
*/
private createWechatPreview(): void {
if (!this.mainDiv) return;
// 创建微信预览容器
this.wechatContainer = this.mainDiv.createDiv({ cls: 'wechat-preview-container' });
// 创建微信预览实例
this.wechatPreview = new WechatPreview(
this.wechatContainer,
this.app,
this.render
);
// 设置回调函数
this.wechatPreview.onRefreshCallback = async () => {
await this.refresh();
};
this.wechatPreview.onAppIdChangeCallback = (appId: string) => {
console.log(`[PreviewManager] 公众号切换: ${appId}`);
// 可以在这里处理公众号切换的额外逻辑
};
// 构建 UI
this.wechatPreview.build();
}
/**
* 创建小红书预览组件
*/
private createXiaohongshuPreview(): void {
if (!this.mainDiv) return;
// 创建小红书预览容器
this.xhsContainer = this.mainDiv.createDiv({ cls: 'xiaohongshu-preview-container' });
// 创建小红书预览实例
this.xhsPreview = new XiaohongshuPreview(this.xhsContainer, this.app);
// 设置回调函数
this.xhsPreview.onRefreshCallback = async () => {
await this.refresh();
};
this.xhsPreview.onPublishCallback = async () => {
await this.publishToXiaohongshu();
};
this.xhsPreview.onPlatformChangeCallback = async (platform: string) => {
if (platform === 'wechat') {
await this.switchPlatform('wechat');
}
};
// 构建 UI
this.xhsPreview.build();
}
/**
* 平台切换的唯一入口
*/
// 平台切换:公开以便外部(例如上下文菜单)调用
async switchPlatform(platform: PlatformType): Promise<void> {
console.log(`[PreviewManager] 平台切换: ${this.currentPlatform}${platform}`);
const previousPlatform = this.currentPlatform;
this.currentPlatform = platform;
// 更新平台选择器显示
if (this.platformChooser) {
this.platformChooser.switchPlatform(platform);
}
if (platform === 'wechat') {
// 显示微信,隐藏小红书
this.showWechat();
this.hideXiaohongshu();
// 如果有当前文件且是从其他平台切换过来,重新渲染
if (this.currentFile && previousPlatform !== 'wechat') {
await this.renderForWechat(this.currentFile);
}
} else if (platform === 'xiaohongshu') {
// 显示小红书,隐藏微信
this.showXiaohongshu();
this.hideWechat();
// 如果有当前文件且是从其他平台切换过来,重新渲染
if (this.currentFile && previousPlatform !== 'xiaohongshu') {
await this.renderForXiaohongshu(this.currentFile);
}
}
}
/**
* 显示微信预览
*/
private showWechat(): void {
if (this.wechatContainer) {
this.wechatContainer.style.display = 'flex';
}
if (this.wechatPreview) {
this.wechatPreview.show();
}
}
/**
* 隐藏微信预览
*/
private hideWechat(): void {
if (this.wechatContainer) {
this.wechatContainer.style.display = 'none';
}
if (this.wechatPreview) {
this.wechatPreview.hide();
}
}
/**
* 显示小红书预览
*/
private showXiaohongshu(): void {
if (this.xhsContainer) {
this.xhsContainer.style.display = 'flex';
}
if (this.xhsPreview) {
this.xhsPreview.show();
}
}
/**
* 隐藏小红书预览
*/
private hideXiaohongshu(): void {
if (this.xhsContainer) {
this.xhsContainer.style.display = 'none';
}
if (this.xhsPreview) {
this.xhsPreview.hide();
}
}
/**
* 设置当前文件(对外接口)
*/
async setFile(file: TFile | null): Promise<void> {
if (!file) {
this.currentFile = null;
this.wechatPreview?.setFile(null);
return;
}
// 只处理 Markdown 文件
if (file.extension.toLowerCase() !== 'md') {
return;
}
console.log(`[PreviewManager] 设置文件: ${file.path}`);
this.currentFile = file;
this.wechatPreview?.setFile(file);
// 根据当前平台渲染
if (this.currentPlatform === 'wechat') {
await this.renderForWechat(file);
} else if (this.currentPlatform === 'xiaohongshu') {
await this.renderForXiaohongshu(file);
}
}
/**
* 刷新预览(对外接口)
*/
async refresh(): Promise<void> {
if (!this.currentFile) {
new Notice('请先打开一个笔记文件');
return;
}
console.log(`[PreviewManager] 刷新预览: ${this.currentFile.path}`);
await this.setFile(this.currentFile);
}
/**
* 渲染微信预览
*/
private async renderForWechat(file: TFile): Promise<void> {
try {
console.log(`[PreviewManager] 渲染微信预览: ${file.path}`);
// 使用 ArticleRender 渲染 Markdown
await this.render.renderMarkdown(file);
// 确保预览持有当前文件引用
this.wechatPreview?.setFile(file);
// 微信预览已经通过 ArticleRender 更新了
// 这里可以添加额外的微信特定逻辑
console.log('[PreviewManager] 微信预览渲染完成');
} catch (error) {
console.error('[PreviewManager] 渲染微信预览失败:', error);
new Notice('渲染失败: ' + (error instanceof Error ? error.message : String(error)));
}
}
/**
* 渲染小红书预览
*/
private async renderForXiaohongshu(file: TFile): Promise<void> {
try {
console.log(`[PreviewManager] 渲染小红书预览: ${file.path}`);
// 使用 ArticleRender 渲染 Markdown
await this.render.renderMarkdown(file);
const articleHTML = this.render.articleHTML;
if (articleHTML && this.xhsPreview) {
// 渲染到小红书预览
await this.xhsPreview.renderArticle(articleHTML, file);
console.log('[PreviewManager] 小红书预览渲染完成');
} else {
console.warn('[PreviewManager] 没有可渲染的内容');
}
} catch (error) {
console.error('[PreviewManager] 渲染小红书预览失败:', error);
new Notice('渲染失败: ' + (error instanceof Error ? error.message : String(error)));
}
}
/**
* 发布到小红书
*/
private async publishToXiaohongshu(): Promise<void> {
console.log('[PreviewManager] 发布到小红书');
// 这里实现发布逻辑
// 可以调用 xhsPreview 的相关方法
new Notice('发布功能开发中...');
}
/**
* 获取当前平台
*/
getCurrentPlatform(): PlatformType {
return this.currentPlatform;
}
/**
* 获取当前文件
*/
getCurrentFile(): TFile | null {
return this.currentFile;
}
/**
* 清理资源
*/
destroy(): void {
console.log('[PreviewManager] 清理资源');
if (this.wechatPreview) {
this.wechatPreview.destroy();
this.wechatPreview = null;
}
if (this.xhsPreview) {
this.xhsPreview.destroy();
this.xhsPreview = null;
}
this.platformChooser = null;
this.mainDiv = null;
this.wechatContainer = null;
this.xhsContainer = null;
this.currentFile = null;
}
/** 获取微信预览实例(发布操作需要) */
getWechatPreview(): WechatPreview | null { return this.wechatPreview; }
}