♻️ Refactor and clean up the code

This commit is contained in:
2025-06-22 21:30:45 +08:00
parent eb9b037f8e
commit d6dd34db87
22 changed files with 357 additions and 843 deletions

View File

@@ -1,6 +1,6 @@
import {defineStore} from 'pinia';
import {computed, reactive} from 'vue';
import {ConfigService, StartupService} from '../../bindings/voidraft/internal/services';
import {ConfigService, StartupService} from '@/../bindings/voidraft/internal/services';
import {
AppConfig,
AppearanceConfig,
@@ -11,7 +11,6 @@ import {
TabType,
} from '@/../bindings/voidraft/internal/models/models';
import {useI18n} from 'vue-i18n';
import {useErrorHandler} from '@/utils/errorHandler';
import {ConfigUtils} from '@/utils/configUtils';
import {WindowController} from '@/utils/windowController';
import * as runtime from '@wailsio/runtime';
@@ -144,11 +143,12 @@ const DEFAULT_CONFIG: AppConfig = {
systemTheme: SystemThemeType.SystemThemeAuto
},
updates: {
Version: "1.0.0",
version: "1.0.0",
autoUpdate: true,
betaChannel: false
},
metadata: {
version: '1.0.0',
lastUpdated: new Date().toString()
}
};
@@ -156,7 +156,6 @@ const DEFAULT_CONFIG: AppConfig = {
export const useConfigStore = defineStore('config', () => {
const {locale} = useI18n();
const {safeCall} = useErrorHandler();
// 响应式状态
const state = reactive({
@@ -250,26 +249,26 @@ export const useConfigStore = defineStore('config', () => {
const clamp = (value: number) => ConfigUtils.clamp(value, limit.min, limit.max);
return {
increase: () => safeCall(() => updateEditingConfig(key, clamp(state.config.editing[key] + 1)), 'config.saveFailed', 'config.saveSuccess'),
decrease: () => safeCall(() => updateEditingConfig(key, clamp(state.config.editing[key] - 1)), 'config.saveFailed', 'config.saveSuccess'),
set: (value: number) => safeCall(() => updateEditingConfig(key, clamp(value)), 'config.saveFailed', 'config.saveSuccess'),
reset: () => safeCall(() => updateEditingConfig(key, limit.default), 'config.saveFailed', 'config.saveSuccess')
increase: async () => await updateEditingConfig(key, clamp(state.config.editing[key] + 1)),
decrease: async () => await updateEditingConfig(key, clamp(state.config.editing[key] - 1)),
set: async (value: number) => await updateEditingConfig(key, clamp(value)),
reset: async () => await updateEditingConfig(key, limit.default)
};
};
// 通用布尔值切换器
const createGeneralToggler = <T extends keyof GeneralConfig>(key: T) =>
() => safeCall(() => updateGeneralConfig(key, !state.config.general[key] as GeneralConfig[T]), 'config.saveFailed', 'config.saveSuccess');
async () => await updateGeneralConfig(key, !state.config.general[key] as GeneralConfig[T]);
const createEditingToggler = <T extends keyof EditingConfig>(key: T) =>
() => safeCall(() => updateEditingConfig(key, !state.config.editing[key] as EditingConfig[T]), 'config.saveFailed', 'config.saveSuccess');
async () => await updateEditingConfig(key, !state.config.editing[key] as EditingConfig[T]);
// 枚举值切换器
const createEnumToggler = <T extends TabType>(key: 'tabType', values: readonly T[]) =>
() => {
async () => {
const currentIndex = values.indexOf(state.config.editing[key] as T);
const nextIndex = (currentIndex + 1) % values.length;
return safeCall(() => updateEditingConfig(key, values[nextIndex]), 'config.saveFailed', 'config.saveSuccess');
return await updateEditingConfig(key, values[nextIndex]);
};
// 重置配置
@@ -278,16 +277,12 @@ export const useConfigStore = defineStore('config', () => {
state.isLoading = true;
try {
// 调用后端重置配置
await safeCall(() => ConfigService.ResetConfig(), 'config.resetFailed', 'config.resetSuccess');
// 立即重新加载后端配置以确保前端状态同步
await safeCall(async () => {
const appConfig = await ConfigService.GetConfig();
if (appConfig) {
state.config = JSON.parse(JSON.stringify(appConfig)) as AppConfig;
}
}, 'config.loadFailed', 'config.loadSuccess');
await ConfigService.ResetConfig()
const appConfig = await ConfigService.GetConfig();
if (appConfig) {
state.config = JSON.parse(JSON.stringify(appConfig)) as AppConfig;
}
} finally {
state.isLoading = false;
}
@@ -295,20 +290,16 @@ export const useConfigStore = defineStore('config', () => {
// 语言设置方法
const setLanguage = async (language: LanguageType): Promise<void> => {
await safeCall(async () => {
await updateAppearanceConfig('language', language);
await updateAppearanceConfig('language', language);
// 同步更新前端语言
const frontendLocale = ConfigUtils.backendLanguageToFrontend(language);
locale.value = frontendLocale as any;
}, 'config.languageChangeFailed', 'config.languageChanged');
// 同步更新前端语言
const frontendLocale = ConfigUtils.backendLanguageToFrontend(language);
locale.value = frontendLocale as any;
};
// 系统主题设置方法
const setSystemTheme = async (systemTheme: SystemThemeType): Promise<void> => {
await safeCall(async () => {
await updateAppearanceConfig('systemTheme', systemTheme);
}, 'config.systemThemeChangeFailed', 'config.systemThemeChanged');
await updateAppearanceConfig('systemTheme', systemTheme);
};
// 初始化语言设置
@@ -339,21 +330,19 @@ export const useConfigStore = defineStore('config', () => {
const togglers = {
tabIndent: createEditingToggler('enableTabIndent'),
alwaysOnTop: async () => {
await safeCall(async () => {
await updateGeneralConfig('alwaysOnTop', !state.config.general.alwaysOnTop);
// 立即应用窗口置顶状态
await runtime.Window.SetAlwaysOnTop(state.config.general.alwaysOnTop);
}, 'config.alwaysOnTopFailed', 'config.alwaysOnTopSuccess');
await updateGeneralConfig('alwaysOnTop', !state.config.general.alwaysOnTop);
// 立即应用窗口置顶状态
await runtime.Window.SetAlwaysOnTop(state.config.general.alwaysOnTop);
},
tabType: createEnumToggler('tabType', CONFIG_LIMITS.tabType.values)
};
// 字符串配置设置器
const setters = {
fontFamily: (value: string) => safeCall(() => updateEditingConfig('fontFamily', value), 'config.saveFailed', 'config.saveSuccess'),
fontWeight: (value: string) => safeCall(() => updateEditingConfig('fontWeight', value), 'config.saveFailed', 'config.saveSuccess'),
dataPath: (value: string) => safeCall(() => updateGeneralConfig('dataPath', value), 'config.saveFailed', 'config.saveSuccess'),
autoSaveDelay: (value: number) => safeCall(() => updateEditingConfig('autoSaveDelay', value), 'config.saveFailed', 'config.saveSuccess')
fontFamily: async (value: string) => await updateEditingConfig('fontFamily', value),
fontWeight: async (value: string) => await updateEditingConfig('fontWeight', value),
dataPath: async (value: string) => await updateGeneralConfig('dataPath', value),
autoSaveDelay: async (value: number) => await updateEditingConfig('autoSaveDelay', value)
};
return {
@@ -366,7 +355,7 @@ export const useConfigStore = defineStore('config', () => {
...limits,
// 核心方法
initConfig: () => safeCall(() => initConfig(), 'config.loadFailed', 'config.loadSuccess'),
initConfig,
resetConfig,
// 语言相关方法
@@ -385,7 +374,7 @@ export const useConfigStore = defineStore('config', () => {
// Tab操作
toggleTabIndent: togglers.tabIndent,
setEnableTabIndent: (value: boolean) => safeCall(() => updateEditingConfig('enableTabIndent', value), 'config.saveFailed', 'config.saveSuccess'),
setEnableTabIndent: (value: boolean) => updateEditingConfig('enableTabIndent', value),
...adjusters.tabSize,
increaseTabSize: adjusters.tabSize.increase,
decreaseTabSize: adjusters.tabSize.decrease,
@@ -397,7 +386,7 @@ export const useConfigStore = defineStore('config', () => {
// 窗口操作
toggleAlwaysOnTop: togglers.alwaysOnTop,
setAlwaysOnTop: (value: boolean) => safeCall(() => updateGeneralConfig('alwaysOnTop', value), 'config.saveFailed', 'config.saveSuccess'),
setAlwaysOnTop: (value: boolean) => updateGeneralConfig('alwaysOnTop', value),
// 字体操作
setFontFamily: setters.fontFamily,
@@ -410,20 +399,18 @@ export const useConfigStore = defineStore('config', () => {
setAutoSaveDelay: setters.autoSaveDelay,
// 热键配置相关方法
setEnableGlobalHotkey: (value: boolean) => safeCall(() => updateGeneralConfig('enableGlobalHotkey', value), 'config.saveFailed', 'config.saveSuccess'),
setGlobalHotkey: (hotkey: any) => safeCall(() => updateGeneralConfig('globalHotkey', hotkey), 'config.saveFailed', 'config.saveSuccess'),
setEnableGlobalHotkey: (value: boolean) => updateGeneralConfig('enableGlobalHotkey', value),
setGlobalHotkey: (hotkey: any) => updateGeneralConfig('globalHotkey', hotkey),
// 系统托盘配置相关方法
setEnableSystemTray: (value: boolean) => safeCall(() => updateGeneralConfig('enableSystemTray', value), 'config.saveFailed', 'config.saveSuccess'),
setEnableSystemTray: (value: boolean) => updateGeneralConfig('enableSystemTray', value),
// 开机启动配置相关方法
setStartAtLogin: async (value: boolean) => {
await safeCall(async () => {
// 先更新配置文件
await updateGeneralConfig('startAtLogin', value);
// 再调用系统设置API
await StartupService.SetEnabled(value);
}, 'config.startupFailed', 'config.startupSuccess');
// 先更新配置文件
await updateGeneralConfig('startAtLogin', value);
// 再调用系统设置API
await StartupService.SetEnabled(value);
}
};
});

View File

@@ -2,11 +2,8 @@ import {defineStore} from 'pinia';
import {computed, ref} from 'vue';
import {DocumentService} from '@/../bindings/voidraft/internal/services';
import {Document} from '@/../bindings/voidraft/internal/models/models';
import {useErrorHandler} from '@/utils/errorHandler';
export const useDocumentStore = defineStore('document', () => {
const {safeCall} = useErrorHandler();
// 状态
const activeDocument = ref<Document | null>(null);
const isLoading = ref(false);
@@ -23,15 +20,13 @@ export const useDocumentStore = defineStore('document', () => {
// 状态管理包装器
const withStateGuard = async <T>(
operation: () => Promise<T>,
stateRef: typeof isLoading | typeof isSaving,
errorMessageKey: string,
successMessageKey?: string
stateRef: typeof isLoading | typeof isSaving
): Promise<T | null> => {
if (stateRef.value) return null;
stateRef.value = true;
try {
return await safeCall(operation, errorMessageKey, successMessageKey);
return await operation();
} finally {
stateRef.value = false;
}
@@ -44,9 +39,7 @@ export const useDocumentStore = defineStore('document', () => {
activeDocument.value = doc;
return doc;
},
isLoading,
'document.loadFailed',
'document.loadSuccess'
isLoading
);
// 保存文档
@@ -64,9 +57,7 @@ export const useDocumentStore = defineStore('document', () => {
return true;
},
isSaving,
'document.saveFailed',
'document.saveSuccess'
isSaving
);
return result ?? false;
@@ -88,9 +79,7 @@ export const useDocumentStore = defineStore('document', () => {
return true;
},
isSaving,
'document.saveFailed',
'document.manualSaveSuccess'
isSaving
);
return result ?? false;

View File

@@ -4,34 +4,29 @@ import {EditorView} from '@codemirror/view';
import {EditorState, Extension} from '@codemirror/state';
import {useConfigStore} from './configStore';
import {useDocumentStore} from './documentStore';
import {useLogStore} from './logStore';
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"
import {createBasicSetup} from '@/views/editor/extensions/basicSetup';
import {
createStatsUpdateExtension,
getTabExtensions,
updateTabConfig,
createAutoSavePlugin,
createSaveShortcutPlugin,
createFontExtensionFromBackend,
updateFontConfig,
createDynamicKeymapExtension,
} from '@/views/editor/extensions';
import { createThemeExtension, updateEditorTheme } from '@/views/editor/extensions/themeExtension';
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"
import {createThemeExtension, updateEditorTheme} from '@/views/editor/extensions/themeExtension';
import {getTabExtensions, updateTabConfig} from '@/views/editor/extensions/tabExtension';
import {createFontExtensionFromBackend, updateFontConfig} from '@/views/editor/extensions/fontExtension';
import {createStatsUpdateExtension} from '@/views/editor/extensions/statsExtension';
import {createAutoSavePlugin, createSaveShortcutPlugin} from '@/views/editor/extensions/autoSaveExtension';
import {createDynamicKeymapExtension} from '@/views/editor/extensions/keymap';
export interface DocumentStats {
lines: number;
characters: number;
selectedCharacters: number;
}
export const useEditorStore = defineStore('editor', () => {
// 引用配置store
const configStore = useConfigStore();
const documentStore = useDocumentStore();
const logStore = useLogStore();
const themeStore = useThemeStore();
const { t } = useI18n();
@@ -100,22 +95,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);
// 然后调用强制保存方法
const success = await documentStore.forceSaveDocument();
if (success) {
logStore.info(t('document.manualSaveSuccess'));
}
};
// 创建编辑器
const createEditor = async (initialDoc: string = '') => {
if (isEditorInitialized.value || !editorContainer.value) return;
@@ -231,6 +210,18 @@ 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 = () => {
@@ -241,51 +232,50 @@ export const useEditorStore = defineStore('editor', () => {
}
};
// 监听Tab设置变化
watch([
() => configStore.config.editing.tabSize,
() => configStore.config.editing.enableTabIndent,
() => configStore.config.editing.tabType,
], () => {
reconfigureTabSettings();
});
// 监听Tab设置变化
watch([
() => configStore.config.editing.tabSize,
() => configStore.config.editing.enableTabIndent,
() => configStore.config.editing.tabType,
], () => {
reconfigureTabSettings();
});
// 监听字体大小变化
watch([
() => configStore.config.editing.fontFamily,
() => configStore.config.editing.fontSize,
() => configStore.config.editing.lineHeight,
() => configStore.config.editing.fontWeight,
], () => {
reconfigureFontSettings();
applyFontSize();
});
// 监听字体大小变化
watch([
() => configStore.config.editing.fontFamily,
() => configStore.config.editing.fontSize,
() => configStore.config.editing.lineHeight,
() => configStore.config.editing.fontWeight,
], () => {
reconfigureFontSettings();
applyFontSize();
});
// 监听主题变化
watch(() => themeStore.currentTheme, (newTheme) => {
if (editorView.value && newTheme) {
updateEditorTheme(editorView.value as EditorView, newTheme);
}
});
// 监听主题变化
watch(() => themeStore.currentTheme, (newTheme) => {
if (editorView.value && newTheme) {
updateEditorTheme(editorView.value as EditorView, newTheme);
}
});
return {
// 状态
documentStats,
editorView,
isEditorInitialized,
editorContainer,
return {
// 状态
documentStats,
editorView,
isEditorInitialized,
editorContainer,
// 方法
setEditorView,
setEditorContainer,
updateDocumentStats,
applyFontSize,
createEditor,
reconfigureTabSettings,
reconfigureFontSettings,
handleManualSave,
destroyEditor,
scrollEditorToBottom,
};
// 方法
setEditorView,
setEditorContainer,
updateDocumentStats,
applyFontSize,
createEditor,
reconfigureTabSettings,
reconfigureFontSettings,
handleManualSave,
destroyEditor,
scrollEditorToBottom,
};
});

View File

@@ -1,166 +0,0 @@
import { defineStore } from 'pinia';
import { ref } from 'vue';
// 日志级别定义
export enum LogLevel {
INFO = 'info',
WARNING = 'warning',
ERROR = 'error'
}
// 日志项结构
export interface LogItem {
id: number;
level: LogLevel;
message: string;
timestamp: Date;
shown: boolean; // 是否已显示过
}
export const useLogStore = defineStore('log', () => {
// 日志列表
const logs = ref<LogItem[]>([]);
// 显示队列 - 存储待显示的日志
const displayQueue = ref<LogItem[]>([]);
// 当前显示的日志
const currentLog = ref<LogItem | null>(null);
// 最近一条日志,用于在工具栏显示
const latestLog = ref<LogItem | null>(null);
// 是否显示日志
const showLog = ref(false);
// 自动隐藏计时器
let hideTimer: number | null = null;
// 根据日志级别获取显示时间
function getDisplayTimeByLevel(level: LogLevel): number {
switch(level) {
case LogLevel.ERROR:
return 8000; // 错误显示更长时间
case LogLevel.WARNING:
return 6000; // 警告显示中等时间
case LogLevel.INFO:
default:
return 4000; // 信息显示较短时间
}
}
// 显示下一条日志
function showNextLog() {
if (hideTimer) {
window.clearTimeout(hideTimer);
hideTimer = null;
}
// 如果队列为空,则不显示
if (displayQueue.value.length === 0) {
showLog.value = false;
currentLog.value = null;
return;
}
// 取出队列中第一条日志显示
const nextLog = displayQueue.value.shift()!;
currentLog.value = nextLog;
showLog.value = true;
// 设置自动隐藏和切换到下一条
const displayTime = getDisplayTimeByLevel(nextLog.level);
hideTimer = window.setTimeout(() => {
showNextLog();
}, displayTime);
}
// 添加日志
function addLog(level: LogLevel, message: string, autoHideDelay = 0) {
const id = Date.now();
const logItem: LogItem = {
id,
level,
message,
timestamp: new Date(),
shown: false
};
// 添加到日志列表
logs.value.push(logItem);
// 保持日志列表在合理大小
if (logs.value.length > 100) {
logs.value = logs.value.slice(-100);
}
// 设置最新日志
latestLog.value = logItem;
// 添加到显示队列
displayQueue.value.push(logItem);
// 如果当前没有显示日志,则开始显示
if (!currentLog.value && !hideTimer) {
showNextLog();
}
return id;
}
// 添加不同级别的日志的便捷方法
function info(message: string) {
return addLog(LogLevel.INFO, message);
}
function warning(message: string) {
return addLog(LogLevel.WARNING, message);
}
function error(message: string) {
return addLog(LogLevel.ERROR, message);
}
// 清除日志
function clearLogs() {
logs.value = [];
displayQueue.value = [];
latestLog.value = null;
currentLog.value = null;
showLog.value = false;
if (hideTimer) {
window.clearTimeout(hideTimer);
hideTimer = null;
}
}
// 手动隐藏当前日志
function hideCurrentLog() {
if (hideTimer) {
window.clearTimeout(hideTimer);
hideTimer = null;
}
showLog.value = false;
currentLog.value = null;
displayQueue.value = []; // 清空队列
}
return {
// 状态
logs,
latestLog,
currentLog,
showLog,
displayQueue,
// 方法
addLog,
info,
warning,
error,
clearLogs,
hideCurrentLog,
showNextLog
};
});