Use SQLite instead of JSON storage

This commit is contained in:
2025-06-29 23:41:34 +08:00
parent 6f8775472d
commit 70d88dabba
25 changed files with 807 additions and 636 deletions

View File

@@ -4,103 +4,113 @@ import {DocumentService} from '@/../bindings/voidraft/internal/services';
import {Document} from '@/../bindings/voidraft/internal/models/models';
export const useDocumentStore = defineStore('document', () => {
// 状态
const activeDocument = ref<Document | null>(null);
const isLoading = ref(false);
const isSaving = ref(false);
const lastSaved = ref<Date | null>(null);
// 计算属性
const documentContent = computed(() => activeDocument.value?.content ?? '');
const documentTitle = computed(() => activeDocument.value?.meta?.title ?? '');
const hasActiveDocument = computed(() => !!activeDocument.value);
const isSaveInProgress = computed(() => isSaving.value);
const lastSavedTime = computed(() => lastSaved.value);
// 加载文档
const loadDocument = async (): Promise<Document | null> => {
if (isLoading.value) return null;
isLoading.value = true;
try {
const doc = await DocumentService.GetActiveDocument();
activeDocument.value = doc;
return doc;
} catch (error) {
return null;
} finally {
isLoading.value = false;
}
};
// 保存文档
const saveDocument = async (content: string): Promise<boolean> => {
if (isSaving.value) return false;
isSaving.value = true;
try {
await DocumentService.UpdateActiveDocumentContent(content);
lastSaved.value = new Date();
// 更新本地副本
if (activeDocument.value) {
activeDocument.value.content = content;
activeDocument.value.meta.lastUpdated = lastSaved.value;
}
return true;
} catch (error) {
return false;
} finally {
isSaving.value = false;
}
};
// 强制保存文档到磁盘
const forceSaveDocument = async (): Promise<boolean> => {
if (isSaving.value) return false;
isSaving.value = true;
try {
await DocumentService.ForceSave();
lastSaved.value = new Date();
// 更新时间戳
if (activeDocument.value) {
activeDocument.value.meta.lastUpdated = lastSaved.value;
}
return true;
} catch (error) {
return false;
} finally {
isSaving.value = false;
}
};
// 初始化
const initialize = async (): Promise<void> => {
await loadDocument();
};
return {
// 状态
activeDocument,
isLoading,
isSaving,
lastSaved,
const currentDocument = ref<Document | null>(null);
const isLoading = ref(false);
const isSaving = ref(false);
const lastSaved = ref<Date | null>(null);
// 计算属性
documentContent,
documentTitle,
hasActiveDocument,
isSaveInProgress,
lastSavedTime,
// 方法
loadDocument,
saveDocument,
forceSaveDocument,
initialize
};
const documentContent = computed(() => currentDocument.value?.content ?? '');
const documentTitle = computed(() => currentDocument.value?.title ?? '');
const hasDocument = computed(() => !!currentDocument.value);
const isSaveInProgress = computed(() => isSaving.value);
const lastSavedTime = computed(() => lastSaved.value);
// 加载文档
const loadDocument = async (documentId = 1): Promise<Document | null> => {
if (isLoading.value) return currentDocument.value;
isLoading.value = true;
try {
const doc = await DocumentService.GetDocumentByID(documentId);
if (doc) {
currentDocument.value = doc;
return doc;
}
return null;
} catch (error) {
return null;
} finally {
isLoading.value = false;
}
};
// 保存文档内容
const saveDocumentContent = async (content: string): Promise<boolean> => {
// 如果内容没有变化,直接返回成功
if (currentDocument.value?.content === content) {
return true;
}
// 如果正在保存中,直接返回
if (isSaving.value) {
return false;
}
isSaving.value = true;
try {
const documentId = currentDocument.value?.id || 1;
await DocumentService.UpdateDocumentContent(documentId, content);
const now = new Date();
lastSaved.value = now;
// 更新本地副本
if (currentDocument.value) {
currentDocument.value.content = content;
currentDocument.value.updatedAt = now;
}
return true;
} catch (error) {
return false;
} finally {
isSaving.value = false;
}
};
// 保存文档标题
const saveDocumentTitle = async (title: string): Promise<boolean> => {
if (!currentDocument.value || currentDocument.value.title === title) {
return true;
}
try {
await DocumentService.UpdateDocumentTitle(currentDocument.value.id, title);
const now = new Date();
lastSaved.value = now;
currentDocument.value.title = title;
currentDocument.value.updatedAt = now;
return true;
} catch (error) {
return false;
}
};
// 初始化
const initialize = async (): Promise<void> => {
await loadDocument();
};
return {
// 状态
currentDocument,
isLoading,
isSaving,
lastSaved,
// 计算属性
documentContent,
documentTitle,
hasDocument,
isSaveInProgress,
lastSavedTime,
// 方法
loadDocument,
saveDocumentContent,
saveDocumentTitle,
initialize
};
});

View File

@@ -5,16 +5,15 @@ import {EditorState, Extension} from '@codemirror/state';
import {useConfigStore} from './configStore';
import {useDocumentStore} from './documentStore';
import {useThemeStore} from './themeStore';
import {useKeybindingStore} from './keybindingStore';
import {SystemThemeType} from '@/../bindings/voidraft/internal/models/models';
import {DocumentService, ExtensionService} from '@/../bindings/voidraft/internal/services';
import {ExtensionService} from '@/../bindings/voidraft/internal/services';
import {ensureSyntaxTree} from "@codemirror/language"
import {createBasicSetup} from '@/views/editor/basic/basicSetup';
import {createThemeExtension, updateEditorTheme} from '@/views/editor/basic/themeExtension';
import {getTabExtensions, updateTabConfig} from '@/views/editor/basic/tabExtension';
import {createFontExtensionFromBackend, updateFontConfig} from '@/views/editor/basic/fontExtension';
import {createStatsUpdateExtension} from '@/views/editor/basic/statsExtension';
import {createAutoSavePlugin, createSaveShortcutPlugin} from '@/views/editor/basic/autoSaveExtension';
import {createAutoSavePlugin} from '@/views/editor/basic/autoSaveExtension';
import {createDynamicKeymapExtension, updateKeymapExtension} from '@/views/editor/keymap';
import {createDynamicExtensions, getExtensionManager, setExtensionManagerView} from '@/views/editor/manager';
import {useExtensionStore} from './extensionStore';
@@ -128,21 +127,10 @@ export const useEditorStore = defineStore('editor', () => {
updateDocumentStats
);
// 创建保存快捷键插件
const saveShortcutExtension = createSaveShortcutPlugin(() => {
if (editorView.value) {
handleManualSave();
}
});
// 创建自动保存插件
const autoSaveExtension = createAutoSavePlugin({
debounceDelay: 300, // 300毫秒的输入防抖
onSave: (success) => {
if (success) {
documentStore.lastSaved = new Date();
}
}
debounceDelay: configStore.config.editing.autoSaveDelay
});
// 代码块功能
const codeBlockExtension = createCodeBlockExtension({
@@ -164,7 +152,6 @@ export const useEditorStore = defineStore('editor', () => {
...tabExtensions,
fontExtension,
statsExtension,
saveShortcutExtension,
autoSaveExtension,
codeBlockExtension,
...dynamicExtensions
@@ -220,19 +207,6 @@ export const useEditorStore = defineStore('editor', () => {
});
};
// 手动保存文档
const handleManualSave = async () => {
if (!editorView.value) return;
const view = editorView.value as EditorView;
const content = view.state.doc.toString();
// 先更新内容
await DocumentService.UpdateActiveDocumentContent(content);
// 然后调用强制保存方法
await documentStore.forceSaveDocument();
};
// 销毁编辑器
const destroyEditor = () => {
if (editorView.value) {
@@ -283,7 +257,7 @@ export const useEditorStore = defineStore('editor', () => {
// 如果需要更新配置
await ExtensionService.UpdateExtensionState(id, enabled, config)
}
// 更新前端编辑器扩展
const manager = getExtensionManager()
if (manager) {
@@ -292,7 +266,7 @@ export const useEditorStore = defineStore('editor', () => {
// 重新加载扩展配置
await extensionStore.loadExtensions()
// 更新快捷键映射
if (editorView.value) {
updateKeymapExtension(editorView.value)
@@ -321,7 +295,6 @@ export const useEditorStore = defineStore('editor', () => {
createEditor,
reconfigureTabSettings,
reconfigureFontSettings,
handleManualSave,
destroyEditor,
updateExtension
};