diff --git a/frontend/bindings/voidraft/internal/models/models.ts b/frontend/bindings/voidraft/internal/models/models.ts index 8da8c69..9e59d82 100644 --- a/frontend/bindings/voidraft/internal/models/models.ts +++ b/frontend/bindings/voidraft/internal/models/models.ts @@ -891,6 +891,11 @@ export class KeyBindingConfig { * KeyBindingMetadata 快捷键配置元数据 */ export class KeyBindingMetadata { + /** + * 配置版本 + */ + "version": string; + /** * 最后更新时间 */ @@ -898,6 +903,9 @@ export class KeyBindingMetadata { /** Creates a new KeyBindingMetadata instance. */ constructor($$source: Partial = {}) { + if (!("version" in $$source)) { + this["version"] = ""; + } if (!("lastUpdated" in $$source)) { this["lastUpdated"] = ""; } diff --git a/frontend/src/i18n/locales/en-US.ts b/frontend/src/i18n/locales/en-US.ts index d5c55d4..58dbd99 100644 --- a/frontend/src/i18n/locales/en-US.ts +++ b/frontend/src/i18n/locales/en-US.ts @@ -19,6 +19,10 @@ export default { noLanguageFound: 'No language found', formatHint: 'Current block supports formatting, use Ctrl+Shift+F shortcut for formatting', }, + languages: { + 'zh-CN': 'Chinese', + 'en-US': 'English' + }, systemTheme: { dark: 'Dark', light: 'Light', diff --git a/frontend/src/i18n/locales/zh-CN.ts b/frontend/src/i18n/locales/zh-CN.ts index 8894516..9d109da 100644 --- a/frontend/src/i18n/locales/zh-CN.ts +++ b/frontend/src/i18n/locales/zh-CN.ts @@ -19,6 +19,10 @@ export default { noLanguageFound: '未找到匹配的语言', formatHint: '当前区块支持格式化,使用 Ctrl+Shift+F 进行格式化', }, + languages: { + 'zh-CN': '简体中文', + 'en-US': 'English' + }, systemTheme: { dark: '深色', light: '浅色', diff --git a/frontend/src/stores/configStore.ts b/frontend/src/stores/configStore.ts index 7442df7..28dcd60 100644 --- a/frontend/src/stores/configStore.ts +++ b/frontend/src/stores/configStore.ts @@ -149,7 +149,7 @@ const DEFAULT_CONFIG: AppConfig = { }, metadata: { version: '1.0.0', - lastUpdated: new Date().toString() + lastUpdated: new Date().toString(), } }; diff --git a/frontend/src/stores/documentStore.ts b/frontend/src/stores/documentStore.ts index 84458e9..9f71fe9 100644 --- a/frontend/src/stores/documentStore.ts +++ b/frontend/src/stores/documentStore.ts @@ -17,76 +17,69 @@ export const useDocumentStore = defineStore('document', () => { const isSaveInProgress = computed(() => isSaving.value); const lastSavedTime = computed(() => lastSaved.value); - // 状态管理包装器 - const withStateGuard = async ( - operation: () => Promise, - stateRef: typeof isLoading | typeof isSaving - ): Promise => { - if (stateRef.value) return null; - - stateRef.value = true; - try { - return await operation(); - } finally { - stateRef.value = false; - } - }; - // 加载文档 - const loadDocument = () => withStateGuard( - async () => { + const loadDocument = async (): Promise => { + if (isLoading.value) return null; + + isLoading.value = true; + try { const doc = await DocumentService.GetActiveDocument(); activeDocument.value = doc; return doc; - }, - isLoading - ); + } catch (error) { + return null; + } finally { + isLoading.value = false; + } + }; // 保存文档 const saveDocument = async (content: string): Promise => { - const result = await withStateGuard( - async () => { - await DocumentService.UpdateActiveDocumentContent(content); - lastSaved.value = new Date(); - - // 使用可选链更新本地副本 - if (activeDocument.value) { - activeDocument.value.content = content; - activeDocument.value.meta.lastUpdated = lastSaved.value; - } - - return true; - }, - isSaving - ); + if (isSaving.value) return false; - return result ?? 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 => { - const result = await withStateGuard( - async () => { - // 直接调用强制保存API - await DocumentService.ForceSave(); - - lastSaved.value = new Date(); - - // 使用可选链更新时间戳 - if (activeDocument.value) { - activeDocument.value.meta.lastUpdated = lastSaved.value; - } - - return true; - }, - isSaving - ); + if (isSaving.value) return false; - return result ?? 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 () => { + const initialize = async (): Promise => { await loadDocument(); }; diff --git a/frontend/src/stores/editorStore.ts b/frontend/src/stores/editorStore.ts index 86a11a4..71166e8 100644 --- a/frontend/src/stores/editorStore.ts +++ b/frontend/src/stores/editorStore.ts @@ -5,7 +5,6 @@ import {EditorState, Extension} from '@codemirror/state'; import {useConfigStore} from './configStore'; import {useDocumentStore} from './documentStore'; import {useThemeStore} from './themeStore'; -import {useI18n} from 'vue-i18n'; import {SystemThemeType} from '@/../bindings/voidraft/internal/models/models'; import {DocumentService} from '@/../bindings/voidraft/internal/services'; import {ensureSyntaxTree} from "@codemirror/language" @@ -28,7 +27,6 @@ export const useEditorStore = defineStore('editor', () => { const configStore = useConfigStore(); const documentStore = useDocumentStore(); const themeStore = useThemeStore(); - const { t } = useI18n(); // 状态 const documentStats = ref({ @@ -267,10 +265,7 @@ export const useEditorStore = defineStore('editor', () => { editorContainer, // 方法 - setEditorView, setEditorContainer, - updateDocumentStats, - applyFontSize, createEditor, reconfigureTabSettings, reconfigureFontSettings, diff --git a/frontend/src/stores/systemStore.ts b/frontend/src/stores/systemStore.ts index 2255366..06ba102 100644 --- a/frontend/src/stores/systemStore.ts +++ b/frontend/src/stores/systemStore.ts @@ -1,5 +1,5 @@ -import { defineStore } from 'pinia'; -import { ref, computed } from 'vue'; +import {defineStore} from 'pinia'; +import {computed, ref} from 'vue'; import * as runtime from '@wailsio/runtime'; export interface SystemEnvironment { @@ -50,8 +50,7 @@ export const useSystemStore = defineStore('system', () => { error.value = null; try { - const env = await runtime.System.Environment(); - environment.value = env; + environment.value = await runtime.System.Environment(); } catch (err) { error.value = 'Failed to get system environment'; environment.value = null; diff --git a/frontend/src/views/settings/pages/GeneralPage.vue b/frontend/src/views/settings/pages/GeneralPage.vue index 2d1b6bc..748fd23 100644 --- a/frontend/src/views/settings/pages/GeneralPage.vue +++ b/frontend/src/views/settings/pages/GeneralPage.vue @@ -5,7 +5,12 @@ import {computed, onUnmounted, ref} from 'vue'; import SettingSection from '../components/SettingSection.vue'; import SettingItem from '../components/SettingItem.vue'; import ToggleSwitch from '../components/ToggleSwitch.vue'; -import {DialogService, MigrationService, MigrationProgress, MigrationStatus} from '@/../bindings/voidraft/internal/services'; +import { + DialogService, + MigrationProgress, + MigrationService, + MigrationStatus +} from '@/../bindings/voidraft/internal/services'; import * as runtime from '@wailsio/runtime'; const {t} = useI18n(); @@ -29,28 +34,28 @@ let hideProgressTimer: any = null; // 开始轮询迁移进度 const startPolling = () => { if (isPolling.value) return; - + isPolling.value = true; showProgress.value = true; progressError.value = ''; - + // 立即重置迁移进度状态,避免从之前的失败状态渐变 migrationProgress.value = new MigrationProgress({ status: MigrationStatus.MigrationStatusMigrating, progress: 0 }); - + pollingTimer = window.setInterval(async () => { try { const progress = await MigrationService.GetProgress(); migrationProgress.value = progress; - const { status, error } = progress; + const {status, error} = progress; const isCompleted = [MigrationStatus.MigrationStatusCompleted, MigrationStatus.MigrationStatusFailed].includes(status); - + if (isCompleted) { stopPolling(); - + // 设置错误信息(如果是失败状态) progressError.value = (status === MigrationStatus.MigrationStatusFailed) ? (error || 'Migration failed') : ''; @@ -59,7 +64,7 @@ const startPolling = () => { } } catch (error) { stopPolling(); - + // 使用常量简化错误处理 const errorMsg = 'Failed to get migration progress'; Object.assign(migrationProgress.value, { @@ -68,7 +73,7 @@ const startPolling = () => { error: errorMsg }); progressError.value = errorMsg; - + hideProgressTimer = setTimeout(hideProgress, 5000); } }, 200); @@ -87,13 +92,13 @@ const stopPolling = () => { const hideProgress = () => { showProgress.value = false; progressError.value = ''; - + // 重置迁移状态,避免下次显示时状态不正确 migrationProgress.value = new MigrationProgress({ status: MigrationStatus.MigrationStatusCompleted, progress: 0 }); - + if (hideProgressTimer) { clearTimeout(hideProgressTimer); hideProgressTimer = null; @@ -110,8 +115,8 @@ const statusClassMap = new Map([ [MigrationStatus.MigrationStatusFailed, 'error'] ]); -const progressBarClass = computed(() => - showProgress.value ? statusClassMap.get(migrationProgress.value.status) ?? '' : '' +const progressBarClass = computed(() => + showProgress.value ? statusClassMap.get(migrationProgress.value.status) ?? '' : '' ); const progressBarWidth = computed(() => { @@ -125,7 +130,7 @@ let resetConfirmTimer: any = null; // 可选键列表 const keyOptions = [ - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12' @@ -210,16 +215,16 @@ const confirmReset = async () => { // 计算热键预览文本 - 使用现代语法简化 const hotkeyPreview = computed(() => { if (!enableGlobalHotkey.value) return ''; - - const { ctrl, shift, alt, win, key } = configStore.config.general.globalHotkey; + + const {ctrl, shift, alt, win, key} = configStore.config.general.globalHotkey; const modifiers = [ ctrl && 'Ctrl', - shift && 'Shift', + shift && 'Shift', alt && 'Alt', win && 'Win', key ].filter(Boolean); - + return modifiers.join(' + '); }); @@ -229,45 +234,42 @@ const currentDataPath = computed(() => configStore.config.general.dataPath); // 选择数据存储目录 const selectDataDirectory = async () => { if (isMigrating.value) return; - - try { - const selectedPath = await DialogService.SelectDirectory(); - - // 检查用户是否取消了选择或路径为空 - if (!selectedPath || !selectedPath.trim() || selectedPath === currentDataPath.value) { - return; - } - const oldPath = currentDataPath.value; - const newPath = selectedPath.trim(); - // 清除之前的进度状态 - hideProgress(); - - // 开始轮询迁移进度 - startPolling(); - - // 开始迁移 - try { - await MigrationService.MigrateDirectory(oldPath, newPath); - await configStore.setDataPath(newPath); - } catch (error) { - stopPolling(); - - // 使用解构和默认值简化错误处理 - const errorMsg = error?.toString() || 'Migration failed'; - showProgress.value = true; - - Object.assign(migrationProgress.value, { - status: MigrationStatus.MigrationStatusFailed, - progress: 0, - error: errorMsg - }); - progressError.value = errorMsg; - - hideProgressTimer = setTimeout(hideProgress, 5000); - } - } catch (dialogError) { - console.error(dialogError); + + const selectedPath = await DialogService.SelectDirectory(); + + // 检查用户是否取消了选择或路径为空 + if (!selectedPath || !selectedPath.trim() || selectedPath === currentDataPath.value) { + return; + } + const oldPath = currentDataPath.value; + const newPath = selectedPath.trim(); + + // 清除之前的进度状态 + hideProgress(); + + // 开始轮询迁移进度 + startPolling(); + + // 开始迁移 + try { + await MigrationService.MigrateDirectory(oldPath, newPath); + await configStore.setDataPath(newPath); + } catch (error) { + stopPolling(); + + // 使用解构和默认值简化错误处理 + const errorMsg = error?.toString() || 'Migration failed'; + showProgress.value = true; + + Object.assign(migrationProgress.value, { + status: MigrationStatus.MigrationStatusFailed, + progress: 0, + error: errorMsg + }); + progressError.value = errorMsg; + + hideProgressTimer = setTimeout(hideProgress, 5000); } }; @@ -287,12 +289,13 @@ onUnmounted(() => { - +
- +
- +
预览: {{ hotkeyPreview || '无' }}
- + @@ -330,13 +335,13 @@ onUnmounted(() => { - + - +
@@ -344,27 +349,27 @@ onUnmounted(() => {
- -
- +
@@ -374,13 +379,13 @@ onUnmounted(() => {
- + -