Complete multi-document mode

This commit is contained in:
2025-07-01 18:16:05 +08:00
parent 70d88dabba
commit 1604564e63
15 changed files with 1368 additions and 431 deletions

View File

@@ -1,109 +0,0 @@
import { EditorView, ViewPlugin, ViewUpdate } from '@codemirror/view';
import { useDocumentStore } from '@/stores/documentStore';
// 自动保存配置选项
export interface AutoSaveOptions {
// 防抖延迟(毫秒)
debounceDelay?: number;
// 保存状态回调
onSaveStart?: () => void;
onSaveSuccess?: () => void;
onSaveError?: () => void;
}
/**
* 简单防抖函数
*/
function debounce<T extends (...args: any[]) => any>(
func: T,
delay: number
): T & { cancel: () => void } {
let timeoutId: number | null = null;
const debounced = ((...args: Parameters<T>) => {
if (timeoutId !== null) {
clearTimeout(timeoutId);
}
timeoutId = window.setTimeout(() => {
timeoutId = null;
func(...args);
}, delay);
}) as T & { cancel: () => void };
debounced.cancel = () => {
if (timeoutId !== null) {
clearTimeout(timeoutId);
timeoutId = null;
}
};
return debounced;
}
/**
* 创建自动保存插件
*/
export function createAutoSavePlugin(options: AutoSaveOptions = {}) {
const {
debounceDelay = 2000,
onSaveStart = () => {},
onSaveSuccess = () => {},
onSaveError = () => {}
} = options;
return ViewPlugin.fromClass(
class AutoSavePlugin {
private documentStore = useDocumentStore();
private debouncedSave: ((content: string) => void) & { cancel: () => void };
private isDestroyed = false;
private lastContent = '';
constructor(private view: EditorView) {
this.lastContent = view.state.doc.toString();
this.debouncedSave = debounce(
(content: string) => this.performSave(content),
debounceDelay
);
}
private async performSave(content: string): Promise<void> {
if (this.isDestroyed) return;
try {
onSaveStart();
const success = await this.documentStore.saveDocumentContent(content);
if (success) {
this.lastContent = content;
onSaveSuccess();
} else {
onSaveError();
}
} catch (error) {
onSaveError();
}
}
update(update: ViewUpdate) {
if (!update.docChanged || this.isDestroyed) return;
const newContent = this.view.state.doc.toString();
if (newContent === this.lastContent) return;
this.debouncedSave(newContent);
}
destroy() {
this.isDestroyed = true;
this.debouncedSave.cancel();
// 如果内容有变化,立即保存
const currentContent = this.view.state.doc.toString();
if (currentContent !== this.lastContent) {
this.documentStore.saveDocumentContent(currentContent).catch(() => {});
}
}
}
);
}

View File

@@ -0,0 +1,39 @@
import { EditorView, ViewPlugin, ViewUpdate } from '@codemirror/view';
import { useDocumentStore } from '@/stores/documentStore';
import { useEditorStore } from '@/stores/editorStore';
/**
* 内容变化监听插件 - 集成文档和编辑器管理
*/
export function createContentChangePlugin() {
return ViewPlugin.fromClass(
class ContentChangePlugin {
private documentStore = useDocumentStore();
private editorStore = useEditorStore();
private lastContent = '';
constructor(private view: EditorView) {
this.lastContent = view.state.doc.toString();
}
update(update: ViewUpdate) {
if (!update.docChanged) return;
const newContent = this.view.state.doc.toString();
if (newContent === this.lastContent) return;
this.lastContent = newContent;
// 通知编辑器管理器内容已变化
const currentDocId = this.documentStore.currentDocumentId;
if (currentDocId) {
this.editorStore.onContentChange(currentDocId);
}
}
destroy() {
}
}
);
}