Files
note2any/ARCHITECTURE_REFACTORING_COMPLETE.md
2025-10-08 19:45:28 +08:00

11 KiB
Raw Blame History

架构重构完成总结 - 引入 PreviewManager 中央调度器

🎯 重构目标

解决循环依赖和职责混乱问题,采用单向数据流 + 中央调度器模式,实现清晰的架构分层。

重构前的问题

循环依赖链

note-preview.ts 
    ↓ 创建实例
platform-chooser.ts 
    ↓ onChange 回调
note-preview.ts 
    ↓ 调用方法
wechat-preview.ts / xhs-preview.ts

主要问题

  1. 职责不清note-preview.ts 既是创建者,又是被调用者
  2. 循环依赖platform-chooser 通过回调反向控制 note-preview
  3. 混乱的控制流:不清楚谁是真正的控制中心

重构后的架构

新的架构图

┌─────────────────────────────────────────────┐
│   Obsidian Framework Layer                  │
│   preview-view.ts (ItemView 容器)           │
│   - 视图生命周期管理                         │
│   - 事件监听注册                             │
│   - 委托所有业务逻辑                         │
└──────────────┬──────────────────────────────┘
               │ 持有并委托
               ↓
┌─────────────────────────────────────────────┐
│   Business Logic Layer                      │
│   preview-manager.ts (中央调度器) ★         │
│   - 创建和管理所有子组件                     │
│   - 处理平台切换(唯一入口)                 │
│   - 协调组件交互                             │
│   - 管理渲染流程                             │
└──────────────┬──────────────────────────────┘
               │ 管理
       ┌───────┼───────┐
       ↓       ↓       ↓
┌──────────┐ ┌──────────┐ ┌──────────┐
│Platform  │ │Wechat    │ │Xiaohong- │
│Chooser   │ │Preview   │ │shu       │
│(UI选择器)│ │(微信实现)│ │Preview   │
└──────────┘ └──────────┘ │(小红书)  │
                           └──────────┘

单向数据流

用户操作 → PlatformChooser.onChange()
              ↓
         PreviewManager.switchPlatform()
              ↓
         ┌────┴────┐
         ↓         ↓
    show/hide  show/hide
    Wechat     Xiaohongshu

📂 文件变更详情

1. 新建 preview-manager.ts (368行)

职责:中央调度器,负责协调所有预览组件

核心功能

  • 创建和管理所有子组件platformChooser, wechatPreview, xhsPreview
  • 平台切换的唯一入口 switchPlatform()
  • 文件渲染协调 setFile(), refresh()
  • 显示/隐藏各平台组件
  • 资源清理 destroy()

关键方法

class PreviewManager {
    async build(): Promise<void>
    private switchPlatform(platform: PlatformType): Promise<void>
    async setFile(file: TFile | null): Promise<void>
    async refresh(): Promise<void>
    private renderForWechat(file: TFile): Promise<void>
    private renderForXiaohongshu(file: TFile): Promise<void>
    destroy(): void
}

2. 重构 preview-view.ts (原 note-preview.ts)

变更:从 895 行简化到 241 行,减少 73%

职责:极简的 Obsidian 视图容器

保留功能

  • 实现 ItemView 接口
  • 管理视图生命周期onOpen/onClose
  • 注册事件监听(文件切换、文件修改)
  • 委托所有业务逻辑给 PreviewManager

关键变更

// 旧版本
class NotePreview extends ItemView {
    // 895 行,包含所有预览逻辑
    buildUI()
    buildToolbar()
    renderMarkdown()
    switchToWechatMode()
    switchToXiaohongshuMode()
    uploadImages()
    postArticle()
    // ... 等大量方法
}

// 新版本
class PreviewView extends ItemView {
    // 241 行,只保留视图容器职责
    private manager: PreviewManager
    async onOpen(): Promise<void>
    async onClose(): Promise<void>
    async setFile(file: TFile): Promise<void>
    async refresh(): Promise<void>
}

3. 更新 platform-chooser.ts

新增方法

setOnChange(callback: (platform: PlatformType) => void): void
switchPlatform(platform: PlatformType): void  // 公开方法,供 PreviewManager 调用

职责分离

  • switchPlatformInternal(): 内部处理用户点击
  • switchPlatform(): 公开方法,供外部程序化切换

4. 更新 xiaohongshu/xhs-preview.ts

新增方法

show(): void   // 显示预览视图
hide(): void   // 隐藏预览视图
destroy(): void // 清理资源

5. 更新 wechat/wechat-preview.ts

已经包含了 show(), hide(), destroy() 方法,无需修改。

6. 更新 main.ts

导入更新

// 旧:
import { NotePreview, VIEW_TYPE_NOTE_PREVIEW } from './note-preview';

// 新:
import { PreviewView, VIEW_TYPE_NOTE_PREVIEW } from './preview-view';

视图注册更新

// 旧:
(leaf) => new NotePreview(leaf, this)

// 新:
(leaf) => new PreviewView(leaf, this)

类型更新

getNotePreview(): PreviewView | null

7. 临时注释功能

由于架构变更,以下功能暂时注释,待后续重构:

main.ts

  • 批量发布命令 (note-to-mp-pub)
  • 右键菜单中的批量发布功能

batch-publish-modal.ts

  • publishToWechat() 方法临时返回错误提示

注意:这些功能会在后续任务中重新实现。

🎨 设计模式应用

1. 中介者模式Mediator Pattern

PreviewManager 作为中介者,协调各组件交互,避免组件间直接依赖。

2. 外观模式Facade Pattern

PreviewManager 对外提供简单接口(setFile, refresh),隐藏内部复杂性。

3. 委托模式Delegation Pattern

PreviewView 将所有业务逻辑委托给 PreviewManager

4. 单一职责原则SRP

  • PreviewView: 只负责 Obsidian 框架集成
  • PreviewManager: 只负责业务逻辑协调
  • PlatformChooser: 只负责平台选择 UI
  • WechatPreview / XhsPreview: 只负责各自平台实现

📊 重构效果对比

指标 重构前 重构后 改善
note-preview.ts 行数 895 241 (preview-view.ts) ↓ 73%
职责明确性 混乱 清晰
循环依赖 存在 消除
可测试性 困难 容易
扩展性

编译验证

npm run build
# ✅ 编译成功!

验证结果

  • TypeScript 编译通过
  • 无类型错误
  • 成功生成 main.js

🔧 调用流程示例

场景:用户切换到小红书平台

// 1. 用户在下拉框选择"小红书"
PlatformChooser.selectElement.onchange()
  
PlatformChooser.switchPlatformInternal('xiaohongshu')
  
PlatformChooser.onChange('xiaohongshu')  // 触发回调
  
PreviewManager.switchPlatform('xiaohongshu')
  
PreviewManager.showXiaohongshu()
  ├─ xhsContainer.style.display = 'flex'
  └─ xhsPreview.show()
  
PreviewManager.hideWechat()
  ├─ wechatContainer.style.display = 'none'
  └─ wechatPreview.hide()
  
PreviewManager.renderForXiaohongshu(currentFile)
  ├─ render.renderMarkdown(file)
  └─ xhsPreview.renderArticle(articleHTML, file)

场景:文件修改自动刷新

// 1. 用户修改当前打开的文件
Obsidian.vault.on('modify', file)
  
PreviewView.handleFileModify(file)
  
PreviewManager.refresh()
  
PreviewManager.setFile(currentFile)
  
// 根据当前平台渲染
if (currentPlatform === 'wechat')
  PreviewManager.renderForWechat(file)
else
  PreviewManager.renderForXiaohongshu(file)

🚀 核心优势

1. 职责清晰,易于理解

PreviewView      → 视图框架集成
PreviewManager   → 业务逻辑协调  ← 核心!
PlatformChooser  → UI 组件
WechatPreview    → 微信实现
XhsPreview       → 小红书实现

2. 消除循环依赖

  • 所有组件只依赖 PreviewManager
  • PreviewManager 作为唯一的协调中心
  • 清晰的单向数据流

3. 易于测试

// 可以独立测试 PreviewManager
const manager = new PreviewManager(mockContainer, mockApp, mockRender);
await manager.build();
await manager.switchPlatform('xiaohongshu');
// 验证行为...

4. 易于扩展

添加新平台(如抖音):

// 1. 创建 douyin/douyin-preview.ts
// 2. 在 PreviewManager 中添加:
private douyinPreview: DouyinPreview;
this.douyinPreview = new DouyinPreview(...);
// 3. 在 switchPlatform 中添加分支
if (platform === 'douyin') {
    this.showDouyin();
    this.hideOthers();
}

5. 减少代码重复

  • 公共逻辑集中在 PreviewManager
  • 各平台只关注自己的特定实现
  • 渲染流程统一管理

📝 待完成工作

高优先级

  1. 重新实现批量发布功能

    • 在 PreviewManager 中添加批量发布方法
    • 更新 batch-publish-modal.ts 调用新接口
    • 恢复右键菜单功能
  2. 完善 WechatPreview 功能

    • 实现 uploadImages()
    • 实现 postArticle()
    • 实现 exportHTML()
    • 从 preview-view-backup.ts 迁移具体实现

中优先级

  1. 添加单元测试

    • 为 PreviewManager 编写测试
    • 为各 Preview 组件编写测试
    • 测试平台切换流程
  2. 优化用户体验

    • 添加平台切换动画
    • 添加加载状态提示
    • 优化错误处理

低优先级

  1. 文档完善
    • 更新 README.md
    • 添加开发文档
    • 添加 API 文档

🎉 总结

本次重构成功实现了:

创建了 PreviewManager 中央调度器368 行)
简化了 PreviewView 为纯视图容器(从 895 行减少到 241 行)
消除了循环依赖(单向数据流)
职责分离清晰(各司其职)
编译成功(无错误)

架构改善

  • 从混乱的双向依赖 → 清晰的单向数据流
  • 从职责不清 → 职责明确的分层架构
  • 从难以测试 → 易于测试的模块化设计
  • 从难以扩展 → 易于扩展的开放架构

下一步:重新实现批量发布功能,完善微信预览功能。


创建时间2025年1月
重构完成:所有 5 项任务完成
编译状态 成功
架构质量