98 lines
2.9 KiB
TypeScript
98 lines
2.9 KiB
TypeScript
import { EditorView, ViewPlugin, ViewUpdate } from '@codemirror/view';
|
|
import { DocumentService } from '@/../bindings/voidraft/internal/services';
|
|
import { useDebounceFn } from '@vueuse/core';
|
|
|
|
// 定义自动保存配置选项
|
|
export interface AutoSaveOptions {
|
|
// 保存回调
|
|
onSave?: (success: boolean) => void;
|
|
// 内容变更延迟传递(毫秒)- 输入时不会立即发送,有一个小延迟,避免频繁调用后端
|
|
debounceDelay?: number;
|
|
}
|
|
|
|
/**
|
|
* 创建自动保存插件
|
|
*
|
|
* @param options 配置选项
|
|
* @returns EditorView.Plugin
|
|
*/
|
|
export function createAutoSavePlugin(options: AutoSaveOptions = {}) {
|
|
const {
|
|
onSave = () => {},
|
|
debounceDelay = 2000
|
|
} = options;
|
|
|
|
return ViewPlugin.fromClass(
|
|
class {
|
|
private isActive: boolean = true;
|
|
private isSaving: boolean = false;
|
|
private readonly contentUpdateFn: (view: EditorView) => void;
|
|
|
|
constructor(private view: EditorView) {
|
|
// 创建内容更新函数,简单传递内容给后端
|
|
this.contentUpdateFn = this.createDebouncedUpdateFn(debounceDelay);
|
|
}
|
|
|
|
/**
|
|
* 创建防抖的内容更新函数
|
|
*/
|
|
private createDebouncedUpdateFn(delay: number): (view: EditorView) => void {
|
|
// 使用VueUse的防抖函数创建一个新函数
|
|
return useDebounceFn(async (view: EditorView) => {
|
|
// 如果插件已不活跃或正在保存中,不发送
|
|
if (!this.isActive || this.isSaving) return;
|
|
|
|
this.isSaving = true;
|
|
const content = view.state.doc.toString();
|
|
|
|
try {
|
|
// 简单将内容传递给后端,让后端处理保存策略
|
|
await DocumentService.UpdateActiveDocumentContent(content);
|
|
onSave(true);
|
|
} catch (err) {
|
|
// 静默处理错误,不在控制台打印
|
|
onSave(false);
|
|
} finally {
|
|
this.isSaving = false;
|
|
}
|
|
}, delay);
|
|
}
|
|
|
|
update(update: ViewUpdate) {
|
|
// 如果内容没有变化,直接返回
|
|
if (!update.docChanged) return;
|
|
|
|
// 调用防抖函数
|
|
this.contentUpdateFn(this.view);
|
|
}
|
|
|
|
destroy() {
|
|
// 标记插件不再活跃
|
|
this.isActive = false;
|
|
|
|
// 静默发送最终内容,忽略错误
|
|
const content = this.view.state.doc.toString();
|
|
DocumentService.UpdateActiveDocumentContent(content).then();
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 创建处理保存快捷键的插件
|
|
* @param onSave 保存回调
|
|
* @returns EditorView.Plugin
|
|
*/
|
|
export function createSaveShortcutPlugin(onSave: () => void) {
|
|
return EditorView.domEventHandlers({
|
|
keydown: (event) => {
|
|
// Ctrl+S / Cmd+S
|
|
if ((event.ctrlKey || event.metaKey) && event.key === 's') {
|
|
event.preventDefault();
|
|
onSave();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
});
|
|
} |