⚡ Performance optimization
This commit is contained in:
@@ -296,7 +296,7 @@ onUnmounted(() => {
|
|||||||
<!-- 选择器按钮 -->
|
<!-- 选择器按钮 -->
|
||||||
<button class="doc-btn" @click="toggleMenu">
|
<button class="doc-btn" @click="toggleMenu">
|
||||||
<span class="doc-name">{{ currentDocName }}</span>
|
<span class="doc-name">{{ currentDocName }}</span>
|
||||||
<span class="arrow" :class="{ open: showMenu }">▼</span>
|
<span class="arrow" :class="{ open: showMenu }">▲</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- 菜单 -->
|
<!-- 菜单 -->
|
||||||
@@ -432,7 +432,7 @@ onUnmounted(() => {
|
|||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
transition: transform 0.2s ease;
|
transition: transform 0.2s ease;
|
||||||
|
|
||||||
&.open {
|
&:not(.open) {
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
import {defineStore} from 'pinia';
|
import {defineStore} from 'pinia';
|
||||||
import {ref, watch, nextTick} from 'vue';
|
import {nextTick, ref, watch} from 'vue';
|
||||||
import {EditorView} from '@codemirror/view';
|
import {EditorView} from '@codemirror/view';
|
||||||
import {EditorState, Extension} from '@codemirror/state';
|
import {EditorState, Extension} from '@codemirror/state';
|
||||||
import {useConfigStore} from './configStore';
|
import {useConfigStore} from './configStore';
|
||||||
import {useDocumentStore} from './documentStore';
|
import {useDocumentStore} from './documentStore';
|
||||||
import {useThemeStore} from './themeStore';
|
import {useThemeStore} from './themeStore';
|
||||||
import {SystemThemeType, ExtensionID} from '@/../bindings/voidraft/internal/models/models';
|
import {ExtensionID, SystemThemeType} from '@/../bindings/voidraft/internal/models/models';
|
||||||
import {DocumentService} from '@/../bindings/voidraft/internal/services';
|
import {DocumentService, ExtensionService} from '@/../bindings/voidraft/internal/services';
|
||||||
import {ensureSyntaxTree} from "@codemirror/language"
|
import {ensureSyntaxTree} from "@codemirror/language";
|
||||||
import {createBasicSetup} from '@/views/editor/basic/basicSetup';
|
import {createBasicSetup} from '@/views/editor/basic/basicSetup';
|
||||||
import {createThemeExtension, updateEditorTheme} from '@/views/editor/basic/themeExtension';
|
import {createThemeExtension, updateEditorTheme} from '@/views/editor/basic/themeExtension';
|
||||||
import {getTabExtensions, updateTabConfig} from '@/views/editor/basic/tabExtension';
|
import {getTabExtensions, updateTabConfig} from '@/views/editor/basic/tabExtension';
|
||||||
@@ -17,7 +17,6 @@ import {createContentChangePlugin} from '@/views/editor/basic/contentChangeExten
|
|||||||
import {createDynamicKeymapExtension, updateKeymapExtension} from '@/views/editor/keymap';
|
import {createDynamicKeymapExtension, updateKeymapExtension} from '@/views/editor/keymap';
|
||||||
import {createDynamicExtensions, getExtensionManager, setExtensionManagerView} from '@/views/editor/manager';
|
import {createDynamicExtensions, getExtensionManager, setExtensionManagerView} from '@/views/editor/manager';
|
||||||
import {useExtensionStore} from './extensionStore';
|
import {useExtensionStore} from './extensionStore';
|
||||||
import {ExtensionService} from '@/../bindings/voidraft/internal/services';
|
|
||||||
import createCodeBlockExtension from "@/views/editor/extensions/codeblock";
|
import createCodeBlockExtension from "@/views/editor/extensions/codeblock";
|
||||||
|
|
||||||
const NUM_EDITOR_INSTANCES = 5; // 最多缓存5个编辑器实例
|
const NUM_EDITOR_INSTANCES = 5; // 最多缓存5个编辑器实例
|
||||||
@@ -35,6 +34,11 @@ interface EditorInstance {
|
|||||||
isDirty: boolean;
|
isDirty: boolean;
|
||||||
lastModified: Date;
|
lastModified: Date;
|
||||||
autoSaveTimer: number | null;
|
autoSaveTimer: number | null;
|
||||||
|
syntaxTreeCache: {
|
||||||
|
lastDocLength: number;
|
||||||
|
lastContentHash: string;
|
||||||
|
lastParsed: Date;
|
||||||
|
} | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useEditorStore = defineStore('editor', () => {
|
export const useEditorStore = defineStore('editor', () => {
|
||||||
@@ -62,17 +66,97 @@ export const useEditorStore = defineStore('editor', () => {
|
|||||||
selectedCharacters: 0
|
selectedCharacters: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 异步操作竞态条件控制
|
||||||
|
const operationSequence = ref(0);
|
||||||
|
const pendingOperations = ref(new Map<number, AbortController>());
|
||||||
|
const currentLoadingDocumentId = ref<number | null>(null);
|
||||||
|
|
||||||
// 自动保存设置 - 从配置动态获取
|
// 自动保存设置 - 从配置动态获取
|
||||||
const getAutoSaveDelay = () => configStore.config.editing.autoSaveDelay;
|
const getAutoSaveDelay = () => configStore.config.editing.autoSaveDelay;
|
||||||
|
|
||||||
|
// 生成新的操作序列号
|
||||||
|
const getNextOperationId = () => ++operationSequence.value;
|
||||||
|
|
||||||
|
// 取消之前的操作
|
||||||
|
const cancelPreviousOperations = (excludeId?: number) => {
|
||||||
|
pendingOperations.value.forEach((controller, id) => {
|
||||||
|
if (id !== excludeId) {
|
||||||
|
controller.abort();
|
||||||
|
pendingOperations.value.delete(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 检查操作是否仍然有效
|
||||||
|
const isOperationValid = (operationId: number, documentId: number) => {
|
||||||
|
return (
|
||||||
|
pendingOperations.value.has(operationId) &&
|
||||||
|
!pendingOperations.value.get(operationId)?.signal.aborted &&
|
||||||
|
currentLoadingDocumentId.value === documentId
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
// === 私有方法 ===
|
// === 私有方法 ===
|
||||||
|
|
||||||
|
// 生成内容哈希
|
||||||
|
const generateContentHash = (content: string): string => {
|
||||||
|
let hash = 0;
|
||||||
|
for (let i = 0; i < content.length; i++) {
|
||||||
|
const char = content.charCodeAt(i);
|
||||||
|
hash = ((hash << 5) - hash) + char;
|
||||||
|
hash = hash & hash; // Convert to 32bit integer
|
||||||
|
}
|
||||||
|
return hash.toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 缓存化的语法树确保方法
|
||||||
|
const ensureSyntaxTreeCached = (view: EditorView, documentId: number): void => {
|
||||||
|
const instance = editorCache.value.instances[documentId];
|
||||||
|
if (!instance) return;
|
||||||
|
|
||||||
|
const docLength = view.state.doc.length;
|
||||||
|
const content = view.state.doc.toString();
|
||||||
|
const contentHash = generateContentHash(content);
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
// 检查是否需要重新构建语法树
|
||||||
|
const cache = instance.syntaxTreeCache;
|
||||||
|
const shouldRebuild = !cache ||
|
||||||
|
cache.lastDocLength !== docLength ||
|
||||||
|
cache.lastContentHash !== contentHash ||
|
||||||
|
(now.getTime() - cache.lastParsed.getTime()) > 30000; // 30秒过期
|
||||||
|
|
||||||
|
if (shouldRebuild) {
|
||||||
|
try {
|
||||||
|
ensureSyntaxTree(view.state, docLength, 5000);
|
||||||
|
|
||||||
|
// 更新缓存
|
||||||
|
instance.syntaxTreeCache = {
|
||||||
|
lastDocLength: docLength,
|
||||||
|
lastContentHash: contentHash,
|
||||||
|
lastParsed: now
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to ensure syntax tree:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 创建编辑器实例
|
// 创建编辑器实例
|
||||||
const createEditorInstance = async (content: string): Promise<EditorView> => {
|
const createEditorInstance = async (
|
||||||
|
content: string,
|
||||||
|
operationId: number,
|
||||||
|
documentId: number
|
||||||
|
): Promise<EditorView> => {
|
||||||
if (!editorCache.value.containerElement) {
|
if (!editorCache.value.containerElement) {
|
||||||
throw new Error('Editor container not set');
|
throw new Error('Editor container not set');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查操作是否仍然有效
|
||||||
|
if (!isOperationValid(operationId, documentId)) {
|
||||||
|
throw new Error('Operation cancelled');
|
||||||
|
}
|
||||||
|
|
||||||
// 获取基本扩展
|
// 获取基本扩展
|
||||||
const basicExtensions = createBasicSetup();
|
const basicExtensions = createBasicSetup();
|
||||||
|
|
||||||
@@ -108,12 +192,27 @@ export const useEditorStore = defineStore('editor', () => {
|
|||||||
enableAutoDetection: true
|
enableAutoDetection: true
|
||||||
});
|
});
|
||||||
|
|
||||||
// 快捷键扩展
|
// 再次检查操作有效性
|
||||||
|
if (!isOperationValid(operationId, documentId)) {
|
||||||
|
throw new Error('Operation cancelled');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 快捷键扩展(异步)
|
||||||
const keymapExtension = await createDynamicKeymapExtension();
|
const keymapExtension = await createDynamicKeymapExtension();
|
||||||
|
|
||||||
// 动态扩展
|
// 检查操作有效性
|
||||||
|
if (!isOperationValid(operationId, documentId)) {
|
||||||
|
throw new Error('Operation cancelled');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 动态扩展(异步)
|
||||||
const dynamicExtensions = await createDynamicExtensions();
|
const dynamicExtensions = await createDynamicExtensions();
|
||||||
|
|
||||||
|
// 最终检查操作有效性
|
||||||
|
if (!isOperationValid(operationId, documentId)) {
|
||||||
|
throw new Error('Operation cancelled');
|
||||||
|
}
|
||||||
|
|
||||||
// 组合所有扩展
|
// 组合所有扩展
|
||||||
const extensions: Extension[] = [
|
const extensions: Extension[] = [
|
||||||
keymapExtension,
|
keymapExtension,
|
||||||
@@ -138,13 +237,11 @@ export const useEditorStore = defineStore('editor', () => {
|
|||||||
state
|
state
|
||||||
});
|
});
|
||||||
|
|
||||||
// 初始化语法树
|
// 将光标定位到文档末尾并滚动到该位置
|
||||||
ensureSyntaxTree(view.state, view.state.doc.length, 5000);
|
|
||||||
|
|
||||||
// 将光标定位到文档末尾
|
|
||||||
const docLength = view.state.doc.length;
|
const docLength = view.state.doc.length;
|
||||||
view.dispatch({
|
view.dispatch({
|
||||||
selection: { anchor: docLength, head: docLength }
|
selection: {anchor: docLength, head: docLength},
|
||||||
|
scrollIntoView: true
|
||||||
});
|
});
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
@@ -177,11 +274,15 @@ export const useEditorStore = defineStore('editor', () => {
|
|||||||
content,
|
content,
|
||||||
isDirty: false,
|
isDirty: false,
|
||||||
lastModified: new Date(),
|
lastModified: new Date(),
|
||||||
autoSaveTimer: null
|
autoSaveTimer: null,
|
||||||
|
syntaxTreeCache: null
|
||||||
};
|
};
|
||||||
|
|
||||||
// 添加到LRU列表
|
// 添加到LRU列表
|
||||||
editorCache.value.lru.push(documentId);
|
editorCache.value.lru.push(documentId);
|
||||||
|
|
||||||
|
// 初始化语法树缓存
|
||||||
|
ensureSyntaxTreeCached(view, documentId);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 更新LRU
|
// 更新LRU
|
||||||
@@ -195,7 +296,11 @@ export const useEditorStore = defineStore('editor', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 获取或创建编辑器
|
// 获取或创建编辑器
|
||||||
const getOrCreateEditor = async (documentId: number, content: string): Promise<EditorView> => {
|
const getOrCreateEditor = async (
|
||||||
|
documentId: number,
|
||||||
|
content: string,
|
||||||
|
operationId: number
|
||||||
|
): Promise<EditorView> => {
|
||||||
// 检查缓存
|
// 检查缓存
|
||||||
const cached = editorCache.value.instances[documentId];
|
const cached = editorCache.value.instances[documentId];
|
||||||
if (cached) {
|
if (cached) {
|
||||||
@@ -203,8 +308,21 @@ export const useEditorStore = defineStore('editor', () => {
|
|||||||
return cached.view;
|
return cached.view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查操作是否仍然有效
|
||||||
|
if (!isOperationValid(operationId, documentId)) {
|
||||||
|
throw new Error('Operation cancelled');
|
||||||
|
}
|
||||||
|
|
||||||
// 创建新的编辑器实例
|
// 创建新的编辑器实例
|
||||||
const view = await createEditorInstance(content);
|
const view = await createEditorInstance(content, operationId, documentId);
|
||||||
|
|
||||||
|
// 最终检查操作有效性
|
||||||
|
if (!isOperationValid(operationId, documentId)) {
|
||||||
|
// 如果操作已取消,清理创建的实例
|
||||||
|
view.destroy();
|
||||||
|
throw new Error('Operation cancelled');
|
||||||
|
}
|
||||||
|
|
||||||
addEditorToCache(documentId, view, content);
|
addEditorToCache(documentId, view, content);
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
@@ -236,13 +354,18 @@ export const useEditorStore = defineStore('editor', () => {
|
|||||||
|
|
||||||
// 重新测量和聚焦编辑器
|
// 重新测量和聚焦编辑器
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
instance.view.requestMeasure();
|
// 将光标定位到文档末尾并滚动到该位置
|
||||||
// 将光标定位到文档末尾
|
|
||||||
const docLength = instance.view.state.doc.length;
|
const docLength = instance.view.state.doc.length;
|
||||||
instance.view.dispatch({
|
instance.view.dispatch({
|
||||||
selection: { anchor: docLength, head: docLength }
|
selection: {anchor: docLength, head: docLength},
|
||||||
|
scrollIntoView: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 滚动到文档底部(将光标位置滚动到可见区域)
|
||||||
instance.view.focus();
|
instance.view.focus();
|
||||||
|
|
||||||
|
// 使用缓存的语法树确保方法
|
||||||
|
ensureSyntaxTreeCached(instance.view, documentId);
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error showing editor:', error);
|
console.error('Error showing editor:', error);
|
||||||
@@ -256,11 +379,17 @@ export const useEditorStore = defineStore('editor', () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const content = instance.view.state.doc.toString();
|
const content = instance.view.state.doc.toString();
|
||||||
|
const lastModified = instance.lastModified;
|
||||||
|
|
||||||
await DocumentService.UpdateDocumentContent(documentId, content);
|
await DocumentService.UpdateDocumentContent(documentId, content);
|
||||||
|
|
||||||
instance.content = content;
|
// 检查在保存期间内容是否又被修改了
|
||||||
instance.isDirty = false;
|
if (instance.lastModified === lastModified) {
|
||||||
instance.lastModified = new Date();
|
instance.content = content;
|
||||||
|
instance.isDirty = false;
|
||||||
|
instance.lastModified = new Date();
|
||||||
|
}
|
||||||
|
// 如果内容在保存期间被修改了,保持 isDirty 状态
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -276,6 +405,9 @@ export const useEditorStore = defineStore('editor', () => {
|
|||||||
|
|
||||||
instance.isDirty = true;
|
instance.isDirty = true;
|
||||||
instance.lastModified = new Date();
|
instance.lastModified = new Date();
|
||||||
|
|
||||||
|
// 清理语法树缓存,下次访问时重新构建
|
||||||
|
instance.syntaxTreeCache = null;
|
||||||
|
|
||||||
// 清除之前的定时器
|
// 清除之前的定时器
|
||||||
if (instance.autoSaveTimer) {
|
if (instance.autoSaveTimer) {
|
||||||
@@ -293,7 +425,7 @@ export const useEditorStore = defineStore('editor', () => {
|
|||||||
// 设置编辑器容器
|
// 设置编辑器容器
|
||||||
const setEditorContainer = (container: HTMLElement | null) => {
|
const setEditorContainer = (container: HTMLElement | null) => {
|
||||||
editorCache.value.containerElement = container;
|
editorCache.value.containerElement = container;
|
||||||
|
|
||||||
// 如果设置容器时已有当前文档,立即加载编辑器
|
// 如果设置容器时已有当前文档,立即加载编辑器
|
||||||
if (container && documentStore.currentDocument) {
|
if (container && documentStore.currentDocument) {
|
||||||
loadEditor(documentStore.currentDocument.id, documentStore.currentDocument.content);
|
loadEditor(documentStore.currentDocument.id, documentStore.currentDocument.content);
|
||||||
@@ -302,22 +434,41 @@ export const useEditorStore = defineStore('editor', () => {
|
|||||||
|
|
||||||
// 加载编辑器
|
// 加载编辑器
|
||||||
const loadEditor = async (documentId: number, content: string) => {
|
const loadEditor = async (documentId: number, content: string) => {
|
||||||
|
// 生成新的操作ID
|
||||||
|
const operationId = getNextOperationId();
|
||||||
|
const abortController = new AbortController();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 验证参数
|
// 验证参数
|
||||||
if (!documentId) {
|
if (!documentId) {
|
||||||
throw new Error('Invalid parameters for loadEditor');
|
throw new Error('Invalid parameters for loadEditor');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 取消之前的操作并设置当前操作
|
||||||
|
cancelPreviousOperations();
|
||||||
|
currentLoadingDocumentId.value = documentId;
|
||||||
|
pendingOperations.value.set(operationId, abortController);
|
||||||
|
|
||||||
// 保存当前编辑器内容
|
// 保存当前编辑器内容
|
||||||
if (currentEditor.value) {
|
if (currentEditor.value) {
|
||||||
const currentDocId = documentStore.currentDocumentId;
|
const currentDocId = documentStore.currentDocumentId;
|
||||||
if (currentDocId && currentDocId !== documentId) {
|
if (currentDocId && currentDocId !== documentId) {
|
||||||
await saveEditorContent(currentDocId);
|
await saveEditorContent(currentDocId);
|
||||||
|
|
||||||
|
// 检查操作是否仍然有效
|
||||||
|
if (!isOperationValid(operationId, documentId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取或创建编辑器
|
// 获取或创建编辑器
|
||||||
const view = await getOrCreateEditor(documentId, content);
|
const view = await getOrCreateEditor(documentId, content, operationId);
|
||||||
|
|
||||||
|
// 检查操作是否仍然有效
|
||||||
|
if (!isOperationValid(operationId, documentId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 更新内容(如果需要)
|
// 更新内容(如果需要)
|
||||||
const instance = editorCache.value.instances[documentId];
|
const instance = editorCache.value.instances[documentId];
|
||||||
@@ -333,14 +484,31 @@ export const useEditorStore = defineStore('editor', () => {
|
|||||||
});
|
});
|
||||||
instance.content = content;
|
instance.content = content;
|
||||||
instance.isDirty = false;
|
instance.isDirty = false;
|
||||||
|
// 清理语法树缓存,因为内容已更新
|
||||||
|
instance.syntaxTreeCache = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 最终检查操作有效性
|
||||||
|
if (!isOperationValid(operationId, documentId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 显示编辑器
|
// 显示编辑器
|
||||||
showEditor(documentId);
|
showEditor(documentId);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
if (error instanceof Error && error.message === 'Operation cancelled') {
|
||||||
|
console.log(`Editor loading cancelled for document ${documentId}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
console.error('Failed to load editor:', error);
|
console.error('Failed to load editor:', error);
|
||||||
|
} finally {
|
||||||
|
// 清理操作记录
|
||||||
|
pendingOperations.value.delete(operationId);
|
||||||
|
if (currentLoadingDocumentId.value === documentId) {
|
||||||
|
currentLoadingDocumentId.value = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -349,27 +517,33 @@ export const useEditorStore = defineStore('editor', () => {
|
|||||||
const instance = editorCache.value.instances[documentId];
|
const instance = editorCache.value.instances[documentId];
|
||||||
if (instance) {
|
if (instance) {
|
||||||
try {
|
try {
|
||||||
|
// 如果正在加载这个文档,取消操作
|
||||||
|
if (currentLoadingDocumentId.value === documentId) {
|
||||||
|
cancelPreviousOperations();
|
||||||
|
currentLoadingDocumentId.value = null;
|
||||||
|
}
|
||||||
|
|
||||||
// 清除自动保存定时器
|
// 清除自动保存定时器
|
||||||
if (instance.autoSaveTimer) {
|
if (instance.autoSaveTimer) {
|
||||||
clearTimeout(instance.autoSaveTimer);
|
clearTimeout(instance.autoSaveTimer);
|
||||||
instance.autoSaveTimer = null;
|
instance.autoSaveTimer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 移除DOM元素
|
// 移除DOM元素
|
||||||
if (instance.view && instance.view.dom && instance.view.dom.parentElement) {
|
if (instance.view && instance.view.dom && instance.view.dom.parentElement) {
|
||||||
instance.view.dom.remove();
|
instance.view.dom.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 销毁编辑器
|
// 销毁编辑器
|
||||||
if (instance.view && instance.view.destroy) {
|
if (instance.view && instance.view.destroy) {
|
||||||
instance.view.destroy();
|
instance.view.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清理引用
|
// 清理引用
|
||||||
if (currentEditor.value === instance.view) {
|
if (currentEditor.value === instance.view) {
|
||||||
currentEditor.value = null;
|
currentEditor.value = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete editorCache.value.instances[documentId];
|
delete editorCache.value.instances[documentId];
|
||||||
|
|
||||||
const lruIndex = editorCache.value.lru.indexOf(documentId);
|
const lruIndex = editorCache.value.lru.indexOf(documentId);
|
||||||
@@ -431,6 +605,10 @@ export const useEditorStore = defineStore('editor', () => {
|
|||||||
|
|
||||||
// 清空所有编辑器
|
// 清空所有编辑器
|
||||||
const clearAllEditors = () => {
|
const clearAllEditors = () => {
|
||||||
|
// 取消所有挂起的操作
|
||||||
|
cancelPreviousOperations();
|
||||||
|
currentLoadingDocumentId.value = null;
|
||||||
|
|
||||||
Object.values(editorCache.value.instances).forEach(instance => {
|
Object.values(editorCache.value.instances).forEach(instance => {
|
||||||
// 清除自动保存定时器
|
// 清除自动保存定时器
|
||||||
if (instance.autoSaveTimer) {
|
if (instance.autoSaveTimer) {
|
||||||
@@ -451,37 +629,36 @@ export const useEditorStore = defineStore('editor', () => {
|
|||||||
|
|
||||||
// 更新扩展
|
// 更新扩展
|
||||||
const updateExtension = async (id: ExtensionID, enabled: boolean, config?: any) => {
|
const updateExtension = async (id: ExtensionID, enabled: boolean, config?: any) => {
|
||||||
try {
|
// 如果只是更新启用状态
|
||||||
// 如果只是更新启用状态
|
if (config === undefined) {
|
||||||
if (config === undefined) {
|
await ExtensionService.UpdateExtensionEnabled(id, enabled);
|
||||||
await ExtensionService.UpdateExtensionEnabled(id, enabled);
|
} else {
|
||||||
} else {
|
// 如果需要更新配置
|
||||||
// 如果需要更新配置
|
await ExtensionService.UpdateExtensionState(id, enabled, config);
|
||||||
await ExtensionService.UpdateExtensionState(id, enabled, config);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 更新前端编辑器扩展
|
// 更新前端编辑器扩展
|
||||||
const manager = getExtensionManager();
|
const manager = getExtensionManager();
|
||||||
if (manager) {
|
if (manager) {
|
||||||
manager.updateExtension(id, enabled, config || {});
|
manager.updateExtension(id, enabled, config || {});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重新加载扩展配置
|
// 重新加载扩展配置
|
||||||
await extensionStore.loadExtensions();
|
await extensionStore.loadExtensions();
|
||||||
|
|
||||||
// 更新快捷键映射
|
// 更新快捷键映射
|
||||||
if (currentEditor.value) {
|
if (currentEditor.value) {
|
||||||
updateKeymapExtension(currentEditor.value);
|
updateKeymapExtension(currentEditor.value);
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 监听文档切换
|
// 监听文档切换
|
||||||
watch(() => documentStore.currentDocument, (newDoc) => {
|
watch(() => documentStore.currentDocument, (newDoc) => {
|
||||||
if (newDoc && editorCache.value.containerElement) {
|
if (newDoc && editorCache.value.containerElement) {
|
||||||
loadEditor(newDoc.id, newDoc.content);
|
// 使用 nextTick 确保DOM更新完成后再加载编辑器
|
||||||
|
nextTick(() => {
|
||||||
|
loadEditor(newDoc.id, newDoc.content);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -512,7 +689,7 @@ export const useEditorStore = defineStore('editor', () => {
|
|||||||
applyThemeSettings,
|
applyThemeSettings,
|
||||||
applyTabSettings,
|
applyTabSettings,
|
||||||
applyKeymapSettings,
|
applyKeymapSettings,
|
||||||
|
|
||||||
// 扩展管理方法
|
// 扩展管理方法
|
||||||
updateExtension,
|
updateExtension,
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user