Files
note2any/docs/ARCHITECTURE_QUICK_REFERENCE.md
2025-10-16 16:26:39 +08:00

964 lines
25 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Note2Any v1.4.0 架构快速参考指南
> **重大更新**: v1.4.0引入了全新的模块化核心系统,本文档为新架构的快速参考。
>
> **相关文档**: [详细架构文档](./architecture-v1.4.0.md) | [升级对比](./ARCHITECTURE_COMPARISON.md)
## 📋 新文件结构
```
src/
├── main.ts # 插件入口 (集成核心模块)
├── preview-view.ts # Obsidian 视图容器 (增强版)
├── preview-manager.ts # 中央调度器 ★
├── platform-chooser.ts # 平台选择器
├── article-render.ts # 内容渲染 (重构中)
├── core/ # 🆕 核心模块系统
│ ├── error-handler.ts # 统一错误处理
│ ├── progress-indicator.ts # 进度反馈系统
│ ├── config-manager.ts # 配置管理中心
│ ├── publisher-interface.ts # 发布平台抽象
│ ├── publisher-manager.ts # 发布管理器
│ ├── content-processor.ts # 内容处理流水线
│ ├── gallery-processor.ts # 图库处理器
│ ├── image-processor.ts # 图像处理引擎
│ └── html-processor.ts # HTML生成器
├── wechat/
│ └── wechat-preview.ts # 微信预览
└── xiaohongshu/
└── xhs-preview.ts # 小红书预览
```
## 🎯 核心模块职责 (v1.4.0 新增)
### 核心支撑层
#### ErrorHandler - 统一错误处理
**职责**
- 全局错误捕获和分类
- 用户友好的错误提示
- 错误日志记录和分析
- 错误恢复策略
**关键方法**
```typescript
ErrorHandler.handle(error: Error, context: string): void
ErrorHandler.log(level: LogLevel, message: string): void
ErrorHandler.getUserFriendlyMessage(error: Error): string
```
**使用示例**
```typescript
try {
await risky_operation();
} catch (error) {
ErrorHandler.handle(error, 'MyModule.doSomething');
// 用户将看到友好的错误提示
}
```
---
#### ProgressIndicator - 进度反馈系统
**职责**
- 长时间操作的进度反馈
- 统一的用户状态提示
- 可视化进度显示
**关键方法**
```typescript
progress.start(message: string): void
progress.update(message: string, progress?: number): void
progress.finish(message: string): void
progress.error(message: string): void
```
**使用示例**
```typescript
const progress = new ProgressIndicator();
progress.start('处理图片');
progress.update('上传第1张图片', 25);
progress.update('上传第2张图片', 50);
progress.finish('图片处理完成');
```
---
#### ConfigManager - 配置管理中心
**职责**
- 中心化配置管理
- 运行时配置验证
- 配置变更通知
- 类型安全的配置访问
**关键方法**
```typescript
ConfigManager.initialize(settings: NMPSettings): void
ConfigManager.getInstance(): ConfigManager
config.get<T>(key: string): T
config.set<T>(key: string, value: T): void
```
**使用示例**
```typescript
const config = ConfigManager.getInstance();
const theme = config.get<string>('defaultStyle');
config.set('enableDebug', true);
```
---
### 发布平台层
#### PublisherInterface & PublisherManager
**职责**
- 统一的平台发布接口
- 平台无关的业务逻辑
- 可扩展的平台架构
**平台接口**
```typescript
interface IPlatformPublisher {
id: string;
name: string;
initialize(config: PlatformConfig): Promise<void>;
publish(content: PublishContent): Promise<PublishResult>;
uploadImage(image: ImageData): Promise<string>;
validateConfig(): ValidationResult;
}
```
**使用示例**
```typescript
const publisherManager = PublisherManager.getInstance();
const result = await publisherManager.publishTo('wechat', content);
```
---
### 内容处理层
#### ContentProcessor - 内容处理流水线
**职责**
- 模块化内容处理
- 可配置的处理管道
- 支持自定义扩展
**处理器接口**
```typescript
interface IContentProcessor {
id: string;
priority: number;
process(content: string, context: ProcessContext): Promise<string>;
}
```
**使用示例**
```typescript
const processor = new ContentProcessor();
processor.addProcessor(new GalleryProcessor());
processor.addProcessor(new ImageProcessor());
const result = await processor.process(markdown);
```
---
#### ImageProcessor - 图像处理引擎
**职责**
- WebP转JPG转换
- 批量图片处理
- 微信图片上传
- HTML转PNG功能
**关键方法**
```typescript
async convertWebpToJpg(data: ArrayBuffer): Promise<ArrayBuffer>
async uploadToWechat(data: ArrayBuffer, filename: string, token: string): Promise<string>
async htmlToPng(element: HTMLElement): Promise<Blob>
```
---
#### GalleryProcessor - 图库处理器
**职责**
- 图库短代码解析
- 本地图片目录扫描
- Wikilink格式转换
**关键方法**
```typescript
async processGalleryShortcodes(content: string): Promise<string>
```
---
#### HtmlProcessor - HTML生成器
**职责**
- HTML文档生成
- CSS样式内联
- 响应式设计优化
- 移动端适配
**关键方法**
```typescript
generateFullHtml(content: string, options: HtmlProcessOptions): string
optimizeForMobile(html: string): string
```
---
## 🔄 新架构调用关系图
```
PreviewView (Obsidian容器)
├─ 集成 ─> ProgressIndicator (进度反馈)
├─ 集成 ─> ErrorHandler (错误处理)
└─ holds ─> PreviewManager (协调者)
├─ 使用 ─> ConfigManager (配置管理)
├─ 使用 ─> PublisherManager (发布管理)
├─ 使用 ─> ContentProcessor (内容处理)
│ │
│ ├─ GalleryProcessor
│ ├─ ImageProcessor
│ └─ HtmlProcessor
├─ creates ─> PlatformChooser
├─ creates ─> WechatPreview
└─ creates ─> XhsPreview
```
---
## 📝 常见任务示例 (v1.4.0)
### 1. 添加新的内容处理器
**步骤一**:实现处理器接口
```typescript
// src/processors/my-processor.ts
import { IContentProcessor, ProcessContext } from '../core/content-processor';
export class MyContentProcessor implements IContentProcessor {
id = 'my-processor';
priority = 100; // 优先级,数字越小越先执行
async process(content: string, context: ProcessContext): Promise<string> {
// 实现自定义处理逻辑
const processed = content.replace(/\{\{custom\}\}/g, '<span class="custom">Custom Content</span>');
return processed;
}
}
```
**步骤二**:注册处理器
```typescript
// src/main.ts 或相关初始化文件
import { MyContentProcessor } from './processors/my-processor';
const contentProcessor = ContentProcessor.getInstance();
contentProcessor.addProcessor(new MyContentProcessor());
```
---
### 2. 添加新平台支持
**步骤一**:实现平台发布接口
```typescript
// src/platforms/my-platform-publisher.ts
import { IPlatformPublisher, PlatformConfig, PublishContent, PublishResult } from '../core/publisher-interface';
export class MyPlatformPublisher implements IPlatformPublisher {
id = 'my-platform';
name = 'My Platform';
async initialize(config: PlatformConfig): Promise<void> {
// 平台初始化逻辑
const progress = new ProgressIndicator();
progress.start('初始化平台连接');
try {
// 验证配置、建立连接等
progress.finish('平台初始化完成');
} catch (error) {
progress.error('平台初始化失败');
ErrorHandler.handle(error, 'MyPlatformPublisher.initialize');
throw error;
}
}
async publish(content: PublishContent): Promise<PublishResult> {
const progress = new ProgressIndicator();
progress.start('发布内容');
try {
// 发布逻辑实现
progress.finish('发布成功');
return { success: true, id: 'published-id' };
} catch (error) {
progress.error('发布失败');
ErrorHandler.handle(error, 'MyPlatformPublisher.publish');
throw error;
}
}
async uploadImage(image: ImageData): Promise<string> {
// 图片上传逻辑
return 'uploaded-image-url';
}
validateConfig(): ValidationResult {
// 配置验证逻辑
return { valid: true };
}
}
```
**步骤二**:注册平台
```typescript
// src/main.ts
import { MyPlatformPublisher } from './platforms/my-platform-publisher';
const publisherManager = PublisherManager.getInstance();
publisherManager.registerPublisher(new MyPlatformPublisher());
```
---
### 3. 使用统一错误处理
**在模块中使用**
```typescript
export class MyModule {
async doSomething() {
const progress = new ProgressIndicator();
progress.start('执行操作');
try {
// 可能出错的操作
await riskyOperation();
progress.finish('操作完成');
} catch (error) {
progress.error('操作失败');
ErrorHandler.handle(error as Error, 'MyModule.doSomething');
// 错误已被处理,用户已看到友好提示
throw error; // 可选:继续抛出供上层处理
}
}
}
```
---
### 4. 配置管理最佳实践
**读取配置**
```typescript
const config = ConfigManager.getInstance();
// 类型安全的配置访问
const theme = config.get<string>('defaultStyle');
const enableDebug = config.get<boolean>('enableDebug');
const timeout = config.get<number>('requestTimeout');
```
**监听配置变更**
```typescript
config.onUpdate((updatedConfig) => {
console.log('配置已更新:', updatedConfig);
// 响应配置变更
});
```
---
## 🐛 调试技巧 (v1.4.0)
### 1. 查看模块状态
在浏览器控制台中:
```javascript
// 查看错误处理器状态
console.log('错误统计:', ErrorHandler.getErrorStats());
// 查看配置管理器状态
const config = ConfigManager.getInstance();
console.log('当前配置:', config.getAll());
// 查看发布管理器状态
const publisherManager = PublisherManager.getInstance();
console.log('可用平台:', publisherManager.listAvailablePublishers());
// 查看内容处理器状态
const contentProcessor = ContentProcessor.getInstance();
console.log('已注册处理器:', contentProcessor.getProcessors());
```
### 2. 启用调试模式
```typescript
// 在开发环境中启用详细日志
const config = ConfigManager.getInstance();
config.set('enableDebug', true);
config.set('logLevel', 'debug');
```
### 3. 错误追踪
```typescript
// 注册错误监听器
ErrorHandler.onError((error, context) => {
console.log(`错误发生在: ${context}`, error);
// 可以发送到错误监控服务
});
```
---
## ⚠️ 注意事项 (v1.4.0)
### 1. 模块初始化顺序
```typescript
// ✅ 正确的初始化顺序
await ErrorHandler.initialize();
await ConfigManager.initialize(settings);
await PublisherManager.initialize();
await ContentProcessor.initialize();
// ❌ 错误ConfigManager 未初始化就使用)
const config = ConfigManager.getInstance(); // 可能抛出错误
```
### 2. 错误处理最佳实践
```typescript
// ✅ 正确(使用统一错误处理)
try {
await operation();
} catch (error) {
ErrorHandler.handle(error, 'Module.method');
}
// ❌ 错误(绕过错误处理系统)
try {
await operation();
} catch (error) {
console.error(error); // 用户不会收到友好提示
}
```
### 3. 进度反馈规范
```typescript
// ✅ 正确(完整的进度生命周期)
const progress = new ProgressIndicator();
progress.start('开始操作');
try {
progress.update('步骤1', 25);
await step1();
progress.update('步骤2', 50);
await step2();
progress.finish('操作完成');
} catch (error) {
progress.error('操作失败');
throw error;
}
// ❌ 错误(没有结束进度指示器)
const progress = new ProgressIndicator();
progress.start('开始操作');
await operation(); // 如果出错,进度指示器会一直显示
```
---
## 🚀 性能优化建议
### 1. 模块懒加载
```typescript
// 按需加载重型模块
const imageProcessor = await import('./core/image-processor');
const processor = new imageProcessor.ImageProcessor();
```
### 2. 缓存优化
```typescript
// 利用配置管理器的缓存
const config = ConfigManager.getInstance();
const cachedTheme = config.get('currentTheme'); // 自动缓存
```
### 3. 批量操作
```typescript
// 使用批量处理API
const imageProcessor = new ImageProcessor();
const results = await imageProcessor.processImages(imageList, options);
```
---
## 📚 相关文档
- [详细架构文档](./architecture-v1.4.0.md) - 完整的架构说明
- [模块开发指南](./module-development-guide.md) - 如何开发新模块
- [发布平台开发](./publisher-development.md) - 如何添加新平台
- [错误处理指南](./error-handling-guide.md) - 错误处理最佳实践
- [性能优化指南](./performance-optimization.md) - 性能优化建议
---
**架构版本**v1.4.0 (模块化核心系统)
**最后更新**2025年10月16日
## 🎯 各文件职责
### preview-view.ts
**角色**Obsidian 视图容器
**职责**
- 实现 `ItemView` 接口
- 管理视图生命周期
- 监听 Obsidian 事件
- 委托业务逻辑给 `PreviewManager`
**关键方法**
```typescript
async onOpen() // 视图打开
async onClose() // 视图关闭
async setFile(file) // 设置文件
async refresh() // 刷新预览
```
---
### preview-manager.ts ★
**角色**:中央调度器(核心)
**职责**
- 创建和管理所有子组件
- 协调平台切换
- 管理文件渲染
- 统一对外接口
**关键方法**
```typescript
async build() // 构建界面
private switchPlatform(platform) // 平台切换(唯一入口)
async setFile(file) // 设置文件
async refresh() // 刷新预览
private renderForWechat(file) // 渲染微信
private renderForXiaohongshu(file) // 渲染小红书
destroy() // 清理资源
```
**创建流程**
```typescript
constructor(container, app, render)
async build()
├─ createPlatformChooser()
├─ createWechatPreview()
└─ createXiaohongshuPreview()
```
---
### platform-chooser.ts
**角色**:平台选择 UI 组件
**职责**
- 渲染平台选择下拉框
- 处理用户选择事件
- 触发平台切换回调
**关键方法**
```typescript
render() // 渲染 UI
setOnChange(callback) // 设置回调
switchPlatform(platform) // 程序化切换
getCurrentPlatform() // 获取当前平台
```
**使用示例**
```typescript
const chooser = new PlatformChooser(container);
chooser.setOnChange((platform) => {
console.log('切换到:', platform);
});
chooser.render();
```
---
### wechat/wechat-preview.ts
**角色**:微信公众号预览实现
**职责**
- 渲染微信专属工具栏
- 处理微信相关操作
- 管理微信公众号配置
**关键方法**
```typescript
build() // 构建 UI
show() // 显示
hide() // 隐藏
updateStyleAndHighlight() // 更新样式
destroy() // 清理
// 待实现
uploadImages() // 上传图片
postArticle() // 发布草稿
exportHTML() // 导出 HTML
```
---
### xiaohongshu/xhs-preview.ts
**角色**:小红书预览实现
**职责**
- 渲染小红书专属界面
- 处理分页和切图
- 管理小红书样式
**关键方法**
```typescript
build() // 构建 UI
show() // 显示
hide() // 隐藏
async renderArticle(html, file) // 渲染文章
destroy() // 清理
```
---
## 🔄 调用关系图
```
PreviewView (视图容器)
├─ holds ─> PreviewManager (协调者)
│ │
│ ├─ creates ─> PlatformChooser
│ │ │
│ │ └─ onChange callback ─┐
│ │ │
│ ├─ creates ─> WechatPreview │
│ │ │ │
│ │ ├─ onRefreshCallback ─┤
│ │ └─ onAppIdChange ─────┤
│ │ │
│ └─ creates ─> XhsPreview │
│ │ │
│ ├─ onRefreshCallback ─────┤
│ ├─ onPublishCallback ─────┤
│ └─ onPlatformChange ──────┤
│ │
└──────────────────────────── all callbacks handled ─────┘
```
---
## 📝 常见任务示例
### 1. 添加新平台(如抖音)
**步骤一**:创建预览组件
```typescript
// src/douyin/douyin-preview.ts
export class DouyinPreview {
container: HTMLElement;
app: any;
constructor(container: HTMLElement, app: any) {
this.container = container;
this.app = app;
}
build(): void {
// 构建抖音专属 UI
}
show(): void {
this.container.style.display = 'flex';
}
hide(): void {
this.container.style.display = 'none';
}
destroy(): void {
// 清理资源
}
}
```
**步骤二**:添加到支持列表
```typescript
// platform-chooser.ts
const SUPPORTED_PLATFORMS: PlatformInfo[] = [
{ value: 'wechat', label: '微信公众号', icon: '📱' },
{ value: 'xiaohongshu', label: '小红书', icon: '📔' },
{ value: 'douyin', label: '抖音', icon: '🎵' } // ← 新增
];
// 更新类型定义
export type PlatformType = 'wechat' | 'xiaohongshu' | 'douyin';
```
**步骤三**:集成到 PreviewManager
```typescript
// preview-manager.ts
import { DouyinPreview } from './douyin/douyin-preview';
export class PreviewManager {
private douyinPreview: DouyinPreview | null = null;
private createDouyinPreview(): void {
const container = this.mainDiv!.createDiv({ cls: 'douyin-preview-container' });
this.douyinPreview = new DouyinPreview(container, this.app);
this.douyinPreview.build();
}
private async switchPlatform(platform: PlatformType): Promise<void> {
// ... 现有代码
if (platform === 'douyin') {
this.showDouyin();
this.hideWechat();
this.hideXiaohongshu();
if (this.currentFile) {
await this.renderForDouyin(this.currentFile);
}
}
}
private async renderForDouyin(file: TFile): Promise<void> {
// 实现抖音渲染逻辑
}
}
```
---
### 2. 修改平台切换逻辑
**位置**`preview-manager.ts`
**方法**`switchPlatform()`
```typescript
private async switchPlatform(platform: PlatformType): Promise<void> {
console.log(`切换平台: ${this.currentPlatform}${platform}`);
const previousPlatform = this.currentPlatform;
this.currentPlatform = platform;
// 更新 UI
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);
}
}
}
```
---
### 3. 添加新的回调函数
**场景**:在微信预览中添加新的操作按钮
**步骤一**:在 WechatPreview 中定义回调
```typescript
// wechat-preview.ts
export class WechatPreview {
onCustomActionCallback?: () => Promise<void>;
private buildToolbar() {
// ... 现有代码
const customBtn = lineDiv.createEl('button', {
text: '自定义操作',
cls: 'toolbar-button'
});
customBtn.onclick = async () => {
if (this.onCustomActionCallback) {
await this.onCustomActionCallback();
}
};
}
}
```
**步骤二**:在 PreviewManager 中设置回调
```typescript
// preview-manager.ts
private createWechatPreview(): void {
// ... 现有代码
this.wechatPreview.onCustomActionCallback = async () => {
await this.handleCustomAction();
};
}
private async handleCustomAction(): Promise<void> {
// 实现自定义操作逻辑
console.log('执行自定义操作');
}
```
---
### 4. 监听文件变化
**位置**`preview-view.ts`
**方法**`registerEventListeners()`
```typescript
private registerEventListeners(): void {
// 监听文件切换
this.listeners.push(
this.app.workspace.on('file-open', async (file: TFile | null) => {
if (this.manager) {
await this.manager.setFile(file);
}
})
);
// 监听文件修改
this.listeners.push(
this.app.vault.on('modify', async (file) => {
if (file instanceof TFile) {
const currentFile = this.manager?.getCurrentFile();
if (currentFile && currentFile.path === file.path) {
await this.manager?.refresh();
}
}
})
);
// 添加新的事件监听
this.listeners.push(
this.app.workspace.on('your-custom-event', async (data) => {
// 处理自定义事件
})
);
}
```
---
## 🐛 调试技巧
### 1. 查看平台切换流程
`preview-manager.ts` 中添加日志:
```typescript
private async switchPlatform(platform: PlatformType): Promise<void> {
console.log(`[PreviewManager] 切换平台: ${this.currentPlatform}${platform}`);
console.log('[PreviewManager] 当前文件:', this.currentFile?.path);
// ... 现有代码
console.log('[PreviewManager] 平台切换完成');
}
```
### 2. 检查组件状态
在浏览器控制台中:
```javascript
// 查看所有预览视图
app.workspace.getLeavesOfType('note-preview')
// 获取 PreviewView 实例
const leaf = app.workspace.getLeavesOfType('note-preview')[0]
const previewView = leaf.view
// 查看 PreviewManager 状态(通过 private 访问需要技巧)
console.log(previewView.manager)
```
### 3. 断点调试
在关键方法中设置断点:
- `PreviewManager.switchPlatform()`
- `PreviewManager.setFile()`
- `PreviewManager.renderForWechat()`
- `PreviewManager.renderForXiaohongshu()`
---
## ⚠️ 注意事项
### 1. 回调函数必须在构建前设置
```typescript
// ✅ 正确
this.wechatPreview = new WechatPreview(...);
this.wechatPreview.onRefreshCallback = async () => { ... };
this.wechatPreview.build();
// ❌ 错误(回调可能不会生效)
this.wechatPreview = new WechatPreview(...);
this.wechatPreview.build();
this.wechatPreview.onRefreshCallback = async () => { ... };
```
### 2. 平台切换不要直接修改 currentPlatform
```typescript
// ❌ 错误(绕过了协调逻辑)
previewManager.currentPlatform = 'xiaohongshu';
// ✅ 正确(通过 switchPlatform
await previewManager.switchPlatform('xiaohongshu');
```
### 3. 清理资源
在组件销毁时必须清理资源:
```typescript
destroy(): void {
// 清理 DOM 引用
this.container = null as any;
// 清理子组件
this.wechatPreview?.destroy();
this.xhsPreview?.destroy();
// 清理回调
this.onRefreshCallback = undefined;
}
```
---
## 📚 相关文档
- [完整重构总结](./ARCHITECTURE_REFACTORING_COMPLETE.md)
- [架构对比](./ARCHITECTURE_COMPARISON.md)
- [平台重构总结](./PLATFORM_REFACTORING_SUMMARY.md)
---
**最后更新**2025年1月
**架构版本**v2.0(引入 PreviewManager