♻️ Refactor and clean up the code
This commit is contained in:
@@ -132,11 +132,19 @@ export class ConfigMetadata {
|
||||
*/
|
||||
"lastUpdated": string;
|
||||
|
||||
/**
|
||||
* 配置版本号
|
||||
*/
|
||||
"version": string;
|
||||
|
||||
/** Creates a new ConfigMetadata instance. */
|
||||
constructor($$source: Partial<ConfigMetadata> = {}) {
|
||||
if (!("lastUpdated" in $$source)) {
|
||||
this["lastUpdated"] = "";
|
||||
}
|
||||
if (!("version" in $$source)) {
|
||||
this["version"] = "";
|
||||
}
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
@@ -978,7 +986,7 @@ export class UpdatesConfig {
|
||||
/**
|
||||
* 当前版本号
|
||||
*/
|
||||
"Version": string;
|
||||
"version": string;
|
||||
|
||||
/**
|
||||
* 是否自动更新
|
||||
@@ -992,8 +1000,8 @@ export class UpdatesConfig {
|
||||
|
||||
/** Creates a new UpdatesConfig instance. */
|
||||
constructor($$source: Partial<UpdatesConfig> = {}) {
|
||||
if (!("Version" in $$source)) {
|
||||
this["Version"] = "";
|
||||
if (!("version" in $$source)) {
|
||||
this["version"] = "";
|
||||
}
|
||||
if (!("autoUpdate" in $$source)) {
|
||||
this["autoUpdate"] = false;
|
||||
|
@@ -2,7 +2,7 @@
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
|
||||
/**
|
||||
* ConfigService 提供基于 Viper 的配置管理功能
|
||||
* ConfigService 应用配置服务
|
||||
* @module
|
||||
*/
|
||||
|
||||
@@ -42,6 +42,14 @@ export function ResetConfig(): Promise<void> & { cancel(): void } {
|
||||
return $resultPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* ServiceShutdown 关闭服务
|
||||
*/
|
||||
export function ServiceShutdown(): Promise<void> & { cancel(): void } {
|
||||
let $resultPromise = $Call.ByID(3963562361) as any;
|
||||
return $resultPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set 设置配置项
|
||||
*/
|
||||
|
@@ -39,10 +39,10 @@ export function GetKeyBindingConfig(): Promise<models$0.KeyBindingConfig | null>
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown 关闭服务
|
||||
* ServiceShutdown 关闭服务
|
||||
*/
|
||||
export function Shutdown(): Promise<void> & { cancel(): void } {
|
||||
let $resultPromise = $Call.ByID(3046465148) as any;
|
||||
export function ServiceShutdown(): Promise<void> & { cancel(): void } {
|
||||
let $resultPromise = $Call.ByID(1610182855) as any;
|
||||
return $resultPromise;
|
||||
}
|
||||
|
||||
|
@@ -3,7 +3,6 @@ import {useI18n} from 'vue-i18n';
|
||||
import {onMounted, onUnmounted, ref, watch} from 'vue';
|
||||
import {useConfigStore} from '@/stores/configStore';
|
||||
import {useEditorStore} from '@/stores/editorStore';
|
||||
import {useErrorHandler} from '@/utils/errorHandler';
|
||||
import * as runtime from '@wailsio/runtime';
|
||||
import {useRouter} from 'vue-router';
|
||||
import BlockLanguageSelector from './BlockLanguageSelector.vue';
|
||||
@@ -12,25 +11,20 @@ import {getLanguage} from '@/views/editor/extensions/codeblock/lang-parser/langu
|
||||
|
||||
const editorStore = useEditorStore();
|
||||
const configStore = useConfigStore();
|
||||
const {safeCall} = useErrorHandler();
|
||||
const {t} = useI18n();
|
||||
const router = useRouter();
|
||||
|
||||
|
||||
// 设置窗口置顶
|
||||
const setWindowAlwaysOnTop = async (isTop: boolean) => {
|
||||
await safeCall(async () => {
|
||||
await runtime.Window.SetAlwaysOnTop(isTop);
|
||||
}, 'window.setTopFailed');
|
||||
await runtime.Window.SetAlwaysOnTop(isTop);
|
||||
};
|
||||
|
||||
// 切换窗口置顶
|
||||
const toggleAlwaysOnTop = async () => {
|
||||
await safeCall(async () => {
|
||||
await configStore.toggleAlwaysOnTop();
|
||||
// 使用Window.SetAlwaysOnTop方法设置窗口置顶状态
|
||||
await runtime.Window.SetAlwaysOnTop(configStore.config.general.alwaysOnTop);
|
||||
}, 'config.alwaysOnTopFailed');
|
||||
await configStore.toggleAlwaysOnTop();
|
||||
// 使用Window.SetAlwaysOnTop方法设置窗口置顶状态
|
||||
await runtime.Window.SetAlwaysOnTop(configStore.config.general.alwaysOnTop);
|
||||
};
|
||||
|
||||
// 跳转到设置页面
|
||||
|
@@ -11,70 +11,19 @@ export default {
|
||||
characters: 'Ch',
|
||||
selected: 'Sel'
|
||||
},
|
||||
fontSize: 'Font Size',
|
||||
fontSizeTooltip: 'Font Size (Ctrl+wheel to adjust)',
|
||||
tabLabel: 'Tab',
|
||||
tabType: {
|
||||
spaces: 'Spaces',
|
||||
tab: 'Tab'
|
||||
},
|
||||
encoding: 'UTF-8',
|
||||
settings: 'Settings',
|
||||
alwaysOnTop: 'Always on Top',
|
||||
blockLanguage: 'Block Language',
|
||||
searchLanguage: 'Search language...',
|
||||
noLanguageFound: 'No language found',
|
||||
autoDetected: 'Auto-detected',
|
||||
formatHint: 'Current block supports formatting, use Ctrl+Shift+F shortcut for formatting',
|
||||
},
|
||||
config: {
|
||||
loadSuccess: 'Configuration loaded successfully',
|
||||
loadFailed: 'Failed to load configuration',
|
||||
saveSuccess: 'Configuration saved',
|
||||
saveFailed: 'Failed to save configuration',
|
||||
resetSuccess: 'Configuration reset to defaults',
|
||||
resetFailed: 'Failed to reset configuration',
|
||||
fontSizeFixed: 'Font size ({value}) has been corrected to {fixed}',
|
||||
tabSizeFixed: 'Tab size ({value}) has been corrected to {fixed}',
|
||||
tabTypeFixed: 'Tab type ({value}) is invalid, corrected to spaces',
|
||||
alwaysOnTopFailed: 'Failed to set window always on top',
|
||||
alwaysOnTopSuccess: 'Window always on top status updated',
|
||||
languageChanged: 'Language setting updated',
|
||||
languageChangeFailed: 'Failed to update language setting',
|
||||
themeChanged: 'Theme setting updated',
|
||||
themeChangeFailed: 'Failed to update theme setting',
|
||||
systemThemeChanged: 'System theme setting updated',
|
||||
systemThemeChangeFailed: 'Failed to update system theme setting',
|
||||
startupSuccess: 'Startup setting updated',
|
||||
startupFailed: 'Failed to update startup setting'
|
||||
},
|
||||
languages: {
|
||||
'zh-CN': '简体中文',
|
||||
'en-US': 'English'
|
||||
},
|
||||
systemTheme: {
|
||||
dark: 'Dark',
|
||||
light: 'Light',
|
||||
auto: 'Follow System'
|
||||
},
|
||||
document: {
|
||||
loadSuccess: 'Document loaded successfully',
|
||||
loadFailed: 'Failed to load document',
|
||||
saveSuccess: 'Document saved successfully',
|
||||
saveFailed: 'Failed to save document',
|
||||
manualSaveSuccess: 'Manually saved successfully',
|
||||
settings: {
|
||||
loadFailed: 'Failed to load save settings',
|
||||
saveSuccess: 'Save settings updated',
|
||||
saveFailed: 'Failed to update save settings'
|
||||
},
|
||||
},
|
||||
migration: {
|
||||
started: 'Starting data migration',
|
||||
migrating: 'Migrating',
|
||||
completed: 'Migration Completed',
|
||||
failed: 'Migration Failed'
|
||||
},
|
||||
keybindings: {
|
||||
headers: {
|
||||
shortcut: 'Shortcut',
|
||||
@@ -88,10 +37,7 @@ export default {
|
||||
searchToggleWord: 'Toggle whole word matching',
|
||||
searchToggleRegex: 'Toggle regular expression matching',
|
||||
searchShowReplace: 'Show replace functionality',
|
||||
searchFindNext: 'Find next match',
|
||||
searchFindPrev: 'Find previous match',
|
||||
searchReplaceAll: 'Replace all matches',
|
||||
searchSelectAll: 'Select all content',
|
||||
blockSelectAll: 'Select all in block',
|
||||
blockAddAfterCurrent: 'Add new block after current',
|
||||
blockAddAfterLast: 'Add new block at end',
|
||||
@@ -125,7 +71,6 @@ export default {
|
||||
selectSyntaxRight: 'Select syntax right',
|
||||
copyLineUp: 'Copy line up',
|
||||
copyLineDown: 'Copy line down',
|
||||
simplifySelection: 'Simplify selection',
|
||||
insertBlankLine: 'Insert blank line',
|
||||
selectLine: 'Select line',
|
||||
selectParentSyntax: 'Select parent syntax',
|
||||
@@ -151,10 +96,7 @@ export default {
|
||||
appearance: 'Appearance',
|
||||
keyBindings: 'Key Bindings',
|
||||
updates: 'Updates',
|
||||
comingSoon: 'Coming Soon...',
|
||||
save: 'Save',
|
||||
reset: 'Reset',
|
||||
cancel: 'Cancel',
|
||||
dangerZone: 'Danger Zone',
|
||||
resetAllSettings: 'Reset All Settings',
|
||||
confirmReset: 'Click again to confirm reset',
|
||||
@@ -171,7 +113,6 @@ export default {
|
||||
clickToSelectPath: 'Click to select path',
|
||||
resetDefault: 'Reset Default',
|
||||
resetToDefaultPath: 'Reset to default path',
|
||||
restartRequiredForDataPath: 'Restart required',
|
||||
fontSize: 'Font Size',
|
||||
fontSizeDescription: 'Editor font size',
|
||||
fontSettings: 'Font Settings',
|
||||
@@ -189,15 +130,7 @@ export default {
|
||||
enableTabIndent: 'Enable Tab Indent',
|
||||
language: 'Interface Language',
|
||||
systemTheme: 'System Theme',
|
||||
theme: 'Editor Theme',
|
||||
themeDescription: 'Choose editor theme',
|
||||
restartRequired: '(Restart required)',
|
||||
saveOptions: 'Save Options',
|
||||
autoSaveDelay: 'Auto Save Delay (ms)',
|
||||
selectDirectoryFailed: 'Failed to select directory',
|
||||
validation: {
|
||||
customPathRequired: 'A valid directory must be selected when enabling custom path',
|
||||
customPathAutoDisabled: 'Custom data path has been automatically disabled due to no valid directory selected'
|
||||
}
|
||||
autoSaveDelay: 'Auto Save Delay (ms)'
|
||||
}
|
||||
};
|
@@ -11,70 +11,19 @@ export default {
|
||||
characters: 'Ch',
|
||||
selected: 'Sel'
|
||||
},
|
||||
fontSize: '字体大小',
|
||||
fontSizeTooltip: '字体大小 (Ctrl+滚轮调整)',
|
||||
tabLabel: 'Tab',
|
||||
tabType: {
|
||||
spaces: '空格',
|
||||
tab: '制表符'
|
||||
},
|
||||
encoding: 'UTF-8',
|
||||
settings: '设置',
|
||||
alwaysOnTop: '窗口置顶',
|
||||
blockLanguage: '块语言',
|
||||
searchLanguage: '搜索语言...',
|
||||
noLanguageFound: '未找到匹配的语言',
|
||||
autoDetected: '自动检测',
|
||||
formatHint: '当前区块支持格式化,使用 Ctrl+Shift+F 进行格式化',
|
||||
},
|
||||
config: {
|
||||
loadSuccess: '配置加载成功',
|
||||
loadFailed: '配置加载失败',
|
||||
saveSuccess: '配置已保存',
|
||||
saveFailed: '配置保存失败',
|
||||
resetSuccess: '配置已重置为默认值',
|
||||
resetFailed: '重置配置失败',
|
||||
fontSizeFixed: '字体大小值({value})已被修正为{fixed}',
|
||||
tabSizeFixed: 'Tab大小值({value})已被修正为{fixed}',
|
||||
tabTypeFixed: 'Tab类型({value})不合法,已修正为空格',
|
||||
alwaysOnTopFailed: '无法设置窗口置顶状态',
|
||||
alwaysOnTopSuccess: '窗口置顶状态已更新',
|
||||
languageChanged: '语言设置已更新',
|
||||
languageChangeFailed: '语言设置更新失败',
|
||||
themeChanged: '主题设置已更新',
|
||||
themeChangeFailed: '主题设置更新失败',
|
||||
systemThemeChanged: '系统主题设置已更新',
|
||||
systemThemeChangeFailed: '系统主题设置更新失败',
|
||||
startupSuccess: '开机启动设置已更新',
|
||||
startupFailed: '开机启动设置失败'
|
||||
},
|
||||
languages: {
|
||||
'zh-CN': '简体中文',
|
||||
'en-US': 'English'
|
||||
},
|
||||
systemTheme: {
|
||||
dark: '深色',
|
||||
light: '浅色',
|
||||
auto: '跟随系统'
|
||||
},
|
||||
document: {
|
||||
loadSuccess: '文档加载成功',
|
||||
loadFailed: '文档加载失败',
|
||||
saveSuccess: '文档保存成功',
|
||||
saveFailed: '文档保存失败',
|
||||
manualSaveSuccess: '手动保存成功',
|
||||
settings: {
|
||||
loadFailed: '加载保存设置失败',
|
||||
saveSuccess: '保存设置已更新',
|
||||
saveFailed: '保存设置更新失败'
|
||||
},
|
||||
},
|
||||
migration: {
|
||||
started: '开始迁移数据',
|
||||
migrating: '迁移中',
|
||||
completed: '迁移已完成',
|
||||
failed: '迁移失败'
|
||||
},
|
||||
keybindings: {
|
||||
headers: {
|
||||
shortcut: '快捷键',
|
||||
@@ -88,10 +37,7 @@ export default {
|
||||
searchToggleWord: '切换整词匹配',
|
||||
searchToggleRegex: '切换正则表达式匹配',
|
||||
searchShowReplace: '显示替换功能',
|
||||
searchFindNext: '查找下一个匹配项',
|
||||
searchFindPrev: '查找上一个匹配项',
|
||||
searchReplaceAll: '替换全部匹配项',
|
||||
searchSelectAll: '选择全部内容',
|
||||
blockSelectAll: '块内选择全部',
|
||||
blockAddAfterCurrent: '在当前块后添加新块',
|
||||
blockAddAfterLast: '在最后添加新块',
|
||||
@@ -125,7 +71,6 @@ export default {
|
||||
selectSyntaxRight: '按语法选择右侧',
|
||||
copyLineUp: '向上复制行',
|
||||
copyLineDown: '向下复制行',
|
||||
simplifySelection: '简化选择',
|
||||
insertBlankLine: '插入空行',
|
||||
selectLine: '选择行',
|
||||
selectParentSyntax: '选择父级语法',
|
||||
@@ -151,10 +96,7 @@ export default {
|
||||
appearance: '外观',
|
||||
keyBindings: '快捷键',
|
||||
updates: '更新',
|
||||
comingSoon: '即将推出...',
|
||||
save: '保存',
|
||||
reset: '重置',
|
||||
cancel: '取消',
|
||||
dangerZone: '危险操作',
|
||||
resetAllSettings: '重置所有设置',
|
||||
confirmReset: '再次点击确认重置',
|
||||
@@ -171,7 +113,6 @@ export default {
|
||||
clickToSelectPath: '点击选择路径',
|
||||
resetDefault: '恢复默认',
|
||||
resetToDefaultPath: '恢复为默认路径',
|
||||
restartRequiredForDataPath: '需要重启应用程序',
|
||||
fontSize: '字体大小',
|
||||
fontSizeDescription: '编辑器字体大小',
|
||||
fontSettings: '字体设置',
|
||||
@@ -189,15 +130,7 @@ export default {
|
||||
enableTabIndent: '启用 Tab 缩进',
|
||||
language: '界面语言',
|
||||
systemTheme: '系统主题',
|
||||
theme: '编辑器主题',
|
||||
themeDescription: '选择编辑器主题',
|
||||
restartRequired: '(需要重启)',
|
||||
saveOptions: '保存选项',
|
||||
autoSaveDelay: '自动保存延迟(毫秒)',
|
||||
selectDirectoryFailed: '选择目录失败',
|
||||
validation: {
|
||||
customPathRequired: '启用自定义路径时必须选择一个有效的目录',
|
||||
customPathAutoDisabled: '由于未选择有效目录,自定义数据路径已自动关闭'
|
||||
}
|
||||
autoSaveDelay: '自动保存延迟(毫秒)'
|
||||
}
|
||||
};
|
@@ -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);
|
||||
}
|
||||
};
|
||||
});
|
@@ -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;
|
||||
|
@@ -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,
|
||||
};
|
||||
});
|
@@ -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
|
||||
};
|
||||
});
|
@@ -1,97 +0,0 @@
|
||||
import { useLogStore } from '@/stores/logStore';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
/**
|
||||
* 创建组合式函数,用于在组件中使用错误处理
|
||||
*/
|
||||
export function useErrorHandler() {
|
||||
const logStore = useLogStore();
|
||||
const { t } = useI18n();
|
||||
|
||||
const handleError = (error: unknown, messageKey: string) => {
|
||||
logStore.error(t(messageKey));
|
||||
};
|
||||
|
||||
const safeCall = async <T>(
|
||||
operation: () => Promise<T>,
|
||||
errorMessageKey: string,
|
||||
successMessageKey?: string
|
||||
): Promise<T | null> => {
|
||||
try {
|
||||
const result = await operation();
|
||||
if (successMessageKey) {
|
||||
logStore.info(t(successMessageKey));
|
||||
}
|
||||
return result;
|
||||
} catch (error) {
|
||||
logStore.error(t(errorMessageKey));
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 静默处理错误,不显示用户提示
|
||||
*/
|
||||
const silentCall = async <T>(
|
||||
operation: () => Promise<T>
|
||||
): Promise<T | null> => {
|
||||
try {
|
||||
return await operation();
|
||||
} catch (error) {
|
||||
// 静默忽略错误
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 创建带错误处理的数值调整器
|
||||
*/
|
||||
const createSafeAdjuster = (
|
||||
adjustFn: () => Promise<void>,
|
||||
errorMessageKey: string
|
||||
) => () => safeCall(adjustFn, errorMessageKey);
|
||||
|
||||
return {
|
||||
handleError,
|
||||
safeCall,
|
||||
silentCall,
|
||||
createSafeAdjuster
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 错误处理工具函数集合(不依赖Vue上下文)
|
||||
*/
|
||||
export const ErrorUtils = {
|
||||
/**
|
||||
* 静默处理错误
|
||||
*/
|
||||
silent: async <T>(operation: () => Promise<T>): Promise<T | null> => {
|
||||
try {
|
||||
return await operation();
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 带重试的错误处理
|
||||
*/
|
||||
withRetry: async <T>(
|
||||
operation: () => Promise<T>,
|
||||
maxRetries: number = 3,
|
||||
delay: number = 1000
|
||||
): Promise<T | null> => {
|
||||
for (let i = 0; i < maxRetries; i++) {
|
||||
try {
|
||||
return await operation();
|
||||
} catch (error) {
|
||||
if (i === maxRetries - 1) {
|
||||
return null;
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, delay));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
@@ -1,7 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { useConfigStore } from '@/stores/configStore';
|
||||
import { useThemeStore } from '@/stores/themeStore';
|
||||
import { useErrorHandler } from '@/utils/errorHandler';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import SettingSection from '../components/SettingSection.vue';
|
||||
import SettingItem from '../components/SettingItem.vue';
|
||||
@@ -10,7 +9,6 @@ import { SystemThemeType, LanguageType } from '@/../bindings/voidraft/internal/m
|
||||
const { t } = useI18n();
|
||||
const configStore = useConfigStore();
|
||||
const themeStore = useThemeStore();
|
||||
const { safeCall } = useErrorHandler();
|
||||
|
||||
// 语言选项
|
||||
const languageOptions = [
|
||||
@@ -30,10 +28,7 @@ const updateLanguage = async (event: Event) => {
|
||||
const select = event.target as HTMLSelectElement;
|
||||
const selectedLanguage = select.value as LanguageType;
|
||||
|
||||
await safeCall(
|
||||
() => configStore.setLanguage(selectedLanguage),
|
||||
'config.languageChangeFailed'
|
||||
);
|
||||
await configStore.setLanguage(selectedLanguage);
|
||||
};
|
||||
|
||||
// 更新系统主题设置
|
||||
@@ -41,10 +36,7 @@ const updateSystemTheme = async (event: Event) => {
|
||||
const select = event.target as HTMLSelectElement;
|
||||
const selectedSystemTheme = select.value as SystemThemeType;
|
||||
|
||||
await safeCall(
|
||||
() => themeStore.setTheme(selectedSystemTheme),
|
||||
'config.systemThemeChangeFailed'
|
||||
);
|
||||
await themeStore.setTheme(selectedSystemTheme);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { useConfigStore } from '@/stores/configStore';
|
||||
import { FONT_OPTIONS } from '@/stores/configStore';
|
||||
import { useErrorHandler } from '@/utils/errorHandler';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import {computed, onMounted } from 'vue';
|
||||
import SettingSection from '../components/SettingSection.vue';
|
||||
@@ -11,7 +10,6 @@ import { TabType } from '@/../bindings/voidraft/internal/models/';
|
||||
|
||||
const { t } = useI18n();
|
||||
const configStore = useConfigStore();
|
||||
const { safeCall } = useErrorHandler();
|
||||
|
||||
// 确保配置已加载
|
||||
onMounted(async () => {
|
||||
@@ -29,10 +27,7 @@ const handleFontFamilyChange = async (event: Event) => {
|
||||
const target = event.target as HTMLSelectElement;
|
||||
const fontFamily = target.value;
|
||||
if (fontFamily) {
|
||||
await safeCall(
|
||||
() => configStore.setFontFamily(fontFamily),
|
||||
'config.fontFamilyUpdateFailed'
|
||||
);
|
||||
await configStore.setFontFamily(fontFamily);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -52,42 +47,27 @@ const fontWeightOptions = [
|
||||
// 字体粗细选择
|
||||
const handleFontWeightChange = async (event: Event) => {
|
||||
const target = event.target as HTMLSelectElement;
|
||||
await safeCall(
|
||||
() => configStore.setFontWeight(target.value),
|
||||
'config.fontWeightUpdateFailed'
|
||||
);
|
||||
await configStore.setFontWeight(target.value);
|
||||
};
|
||||
|
||||
// 行高控制
|
||||
const increaseLineHeight = async () => {
|
||||
const newLineHeight = Math.min(3.0, configStore.config.editing.lineHeight + 0.1);
|
||||
await safeCall(
|
||||
() => configStore.setLineHeight(Math.round(newLineHeight * 10) / 10),
|
||||
'config.lineHeightIncreaseFailed'
|
||||
);
|
||||
await configStore.setLineHeight(Math.round(newLineHeight * 10) / 10);
|
||||
};
|
||||
|
||||
const decreaseLineHeight = async () => {
|
||||
const newLineHeight = Math.max(1.0, configStore.config.editing.lineHeight - 0.1);
|
||||
await safeCall(
|
||||
() => configStore.setLineHeight(Math.round(newLineHeight * 10) / 10),
|
||||
'config.lineHeightDecreaseFailed'
|
||||
);
|
||||
await configStore.setLineHeight(Math.round(newLineHeight * 10) / 10);
|
||||
};
|
||||
|
||||
// 字体大小控制
|
||||
const increaseFontSize = async () => {
|
||||
await safeCall(
|
||||
() => configStore.increaseFontSize(),
|
||||
'config.fontSizeIncreaseFailed'
|
||||
);
|
||||
await configStore.increaseFontSize();
|
||||
};
|
||||
|
||||
const decreaseFontSize = async () => {
|
||||
await safeCall(
|
||||
() => configStore.decreaseFontSize(),
|
||||
'config.fontSizeDecreaseFailed'
|
||||
);
|
||||
await configStore.decreaseFontSize();
|
||||
};
|
||||
|
||||
// Tab类型切换
|
||||
@@ -99,35 +79,23 @@ const tabTypeText = computed(() => {
|
||||
|
||||
// Tab大小增减
|
||||
const increaseTabSize = async () => {
|
||||
await safeCall(
|
||||
() => configStore.increaseTabSize(),
|
||||
'config.tabSizeIncreaseFailed'
|
||||
);
|
||||
await configStore.increaseTabSize();
|
||||
};
|
||||
|
||||
const decreaseTabSize = async () => {
|
||||
await safeCall(
|
||||
() => configStore.decreaseTabSize(),
|
||||
'config.tabSizeDecreaseFailed'
|
||||
);
|
||||
await configStore.decreaseTabSize();
|
||||
};
|
||||
|
||||
// Tab相关操作
|
||||
const handleToggleTabType = async () => {
|
||||
await safeCall(
|
||||
() => configStore.toggleTabType(),
|
||||
'config.tabTypeToggleFailed'
|
||||
);
|
||||
await configStore.toggleTabType();
|
||||
};
|
||||
|
||||
// 创建双向绑定的计算属性
|
||||
const enableTabIndent = computed({
|
||||
get: () => configStore.config.editing.enableTabIndent,
|
||||
set: async (value: boolean) => {
|
||||
await safeCall(
|
||||
() => configStore.setEnableTabIndent(value),
|
||||
'config.tabIndentToggleFailed'
|
||||
);
|
||||
await configStore.setEnableTabIndent(value);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -136,10 +104,7 @@ const handleAutoSaveDelayChange = async (event: Event) => {
|
||||
const target = event.target as HTMLInputElement;
|
||||
const value = parseInt(target.value, 10);
|
||||
if (!isNaN(value) && value >= 1000 && value <= 30000) {
|
||||
await safeCall(
|
||||
() => configStore.setAutoSaveDelay(value),
|
||||
'config.autoSaveDelayUpdateFailed'
|
||||
);
|
||||
await configStore.setAutoSaveDelay(value);
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -5,13 +5,11 @@ 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 {useErrorHandler} from '@/utils/errorHandler';
|
||||
import {DialogService, MigrationService, MigrationProgress, MigrationStatus} from '@/../bindings/voidraft/internal/services';
|
||||
import * as runtime from '@wailsio/runtime';
|
||||
|
||||
const {t} = useI18n();
|
||||
const configStore = useConfigStore();
|
||||
const {safeCall} = useErrorHandler();
|
||||
|
||||
// 迁移进度状态
|
||||
const migrationProgress = ref<MigrationProgress>(new MigrationProgress({
|
||||
@@ -143,12 +141,10 @@ const enableGlobalHotkey = computed({
|
||||
const alwaysOnTop = computed({
|
||||
get: () => configStore.config.general.alwaysOnTop,
|
||||
set: async (value: boolean) => {
|
||||
await safeCall(async () => {
|
||||
// 先更新配置
|
||||
await configStore.setAlwaysOnTop(value);
|
||||
// 然后立即应用窗口置顶状态
|
||||
await runtime.Window.SetAlwaysOnTop(value);
|
||||
}, 'config.alwaysOnTopFailed', 'config.alwaysOnTopSuccess');
|
||||
// 先更新配置
|
||||
await configStore.setAlwaysOnTop(value);
|
||||
// 然后立即应用窗口置顶状态
|
||||
await runtime.Window.SetAlwaysOnTop(value);
|
||||
}
|
||||
});
|
||||
|
||||
|
Reference in New Issue
Block a user