🎨 Change configuration structure

This commit is contained in:
2025-06-03 00:19:16 +08:00
parent 77bd15bed7
commit 81868e8d37
12 changed files with 525 additions and 386 deletions

View File

@@ -10,23 +10,33 @@ import {Create as $Create} from "@wailsio/runtime";
import * as time$0 from "../../../time/models.js"; import * as time$0 from "../../../time/models.js";
/** /**
* AppConfig 应用配置 - 包含业务配置和路径配置 * AppConfig 应用配置 - 按照前端设置页面分类组织
*/ */
export class AppConfig { export class AppConfig {
/** /**
* 编辑器配 * 通用设
*/ */
"editor": EditorConfig; "general": GeneralConfig;
/** /**
* 文档配 * 编辑设
*/ */
"document": DocumentConfig; "editing": EditingConfig;
/** /**
* 路径配 * 外观设
*/ */
"paths": PathsConfig; "appearance": AppearanceConfig;
/**
* 快捷键设置
*/
"keyBindings": KeyBindingsConfig;
/**
* 更新设置
*/
"updates": UpdatesConfig;
/** /**
* 配置元数据 * 配置元数据
@@ -35,14 +45,20 @@ export class AppConfig {
/** Creates a new AppConfig instance. */ /** Creates a new AppConfig instance. */
constructor($$source: Partial<AppConfig> = {}) { constructor($$source: Partial<AppConfig> = {}) {
if (!("editor" in $$source)) { if (!("general" in $$source)) {
this["editor"] = (new EditorConfig()); this["general"] = (new GeneralConfig());
} }
if (!("document" in $$source)) { if (!("editing" in $$source)) {
this["document"] = (new DocumentConfig()); this["editing"] = (new EditingConfig());
} }
if (!("paths" in $$source)) { if (!("appearance" in $$source)) {
this["paths"] = (new PathsConfig()); this["appearance"] = (new AppearanceConfig());
}
if (!("keyBindings" in $$source)) {
this["keyBindings"] = (new KeyBindingsConfig());
}
if (!("updates" in $$source)) {
this["updates"] = (new UpdatesConfig());
} }
if (!("metadata" in $$source)) { if (!("metadata" in $$source)) {
this["metadata"] = (new ConfigMetadata()); this["metadata"] = (new ConfigMetadata());
@@ -59,23 +75,58 @@ export class AppConfig {
const $$createField1_0 = $$createType1; const $$createField1_0 = $$createType1;
const $$createField2_0 = $$createType2; const $$createField2_0 = $$createType2;
const $$createField3_0 = $$createType3; const $$createField3_0 = $$createType3;
const $$createField4_0 = $$createType4;
const $$createField5_0 = $$createType5;
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
if ("editor" in $$parsedSource) { if ("general" in $$parsedSource) {
$$parsedSource["editor"] = $$createField0_0($$parsedSource["editor"]); $$parsedSource["general"] = $$createField0_0($$parsedSource["general"]);
} }
if ("document" in $$parsedSource) { if ("editing" in $$parsedSource) {
$$parsedSource["document"] = $$createField1_0($$parsedSource["document"]); $$parsedSource["editing"] = $$createField1_0($$parsedSource["editing"]);
} }
if ("paths" in $$parsedSource) { if ("appearance" in $$parsedSource) {
$$parsedSource["paths"] = $$createField2_0($$parsedSource["paths"]); $$parsedSource["appearance"] = $$createField2_0($$parsedSource["appearance"]);
}
if ("keyBindings" in $$parsedSource) {
$$parsedSource["keyBindings"] = $$createField3_0($$parsedSource["keyBindings"]);
}
if ("updates" in $$parsedSource) {
$$parsedSource["updates"] = $$createField4_0($$parsedSource["updates"]);
} }
if ("metadata" in $$parsedSource) { if ("metadata" in $$parsedSource) {
$$parsedSource["metadata"] = $$createField3_0($$parsedSource["metadata"]); $$parsedSource["metadata"] = $$createField5_0($$parsedSource["metadata"]);
} }
return new AppConfig($$parsedSource as Partial<AppConfig>); return new AppConfig($$parsedSource as Partial<AppConfig>);
} }
} }
/**
* AppearanceConfig 外观设置配置
*/
export class AppearanceConfig {
/**
* 界面语言
*/
"language": LanguageType;
/** Creates a new AppearanceConfig instance. */
constructor($$source: Partial<AppearanceConfig> = {}) {
if (!("language" in $$source)) {
this["language"] = ("" as LanguageType);
}
Object.assign(this, $$source);
}
/**
* Creates a new AppearanceConfig instance from a string or object.
*/
static createFrom($$source: any = {}): AppearanceConfig {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
return new AppearanceConfig($$parsedSource as Partial<AppearanceConfig>);
}
}
/** /**
* ConfigMetadata 配置元数据 * ConfigMetadata 配置元数据
*/ */
@@ -141,7 +192,7 @@ export class Document {
* Creates a new Document instance from a string or object. * Creates a new Document instance from a string or object.
*/ */
static createFrom($$source: any = {}): Document { static createFrom($$source: any = {}): Document {
const $$createField0_0 = $$createType4; const $$createField0_0 = $$createType6;
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
if ("meta" in $$parsedSource) { if ("meta" in $$parsedSource) {
$$parsedSource["meta"] = $$createField0_0($$parsedSource["meta"]); $$parsedSource["meta"] = $$createField0_0($$parsedSource["meta"]);
@@ -150,49 +201,6 @@ export class Document {
} }
} }
/**
* DocumentConfig 定义文档配置
*/
export class DocumentConfig {
/**
* 自动保存延迟(毫秒)- 内容变更后多久自动保存
*/
"autoSaveDelay": number;
/**
* 变更字符阈值,超过此阈值立即触发保存
*/
"changeThreshold": number;
/**
* 最小保存间隔(毫秒)- 两次保存之间的最小时间间隔避免频繁IO
*/
"minSaveInterval": number;
/** Creates a new DocumentConfig instance. */
constructor($$source: Partial<DocumentConfig> = {}) {
if (!("autoSaveDelay" in $$source)) {
this["autoSaveDelay"] = 0;
}
if (!("changeThreshold" in $$source)) {
this["changeThreshold"] = 0;
}
if (!("minSaveInterval" in $$source)) {
this["minSaveInterval"] = 0;
}
Object.assign(this, $$source);
}
/**
* Creates a new DocumentConfig instance from a string or object.
*/
static createFrom($$source: any = {}): DocumentConfig {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
return new DocumentConfig($$parsedSource as Partial<DocumentConfig>);
}
}
/** /**
* DocumentMeta 文档元数据 * DocumentMeta 文档元数据
*/ */
@@ -245,10 +253,11 @@ export class DocumentMeta {
} }
/** /**
* EditorConfig 定义编辑器配置 * EditingConfig 编辑设置配置
*/ */
export class EditorConfig { export class EditingConfig {
/** /**
* 字体设置
* 字体大小 * 字体大小
*/ */
"fontSize": number; "fontSize": number;
@@ -269,6 +278,7 @@ export class EditorConfig {
"lineHeight": number; "lineHeight": number;
/** /**
* Tab设置
* 是否启用Tab缩进 * 是否启用Tab缩进
*/ */
"enableTabIndent": boolean; "enableTabIndent": boolean;
@@ -284,17 +294,23 @@ export class EditorConfig {
"tabType": TabType; "tabType": TabType;
/** /**
* 界面语言 * 保存选项
* 自动保存延迟(毫秒)
*/ */
"language": LanguageType; "autoSaveDelay": number;
/** /**
* 窗口是否置顶 * 变更字符阈值
*/ */
"alwaysOnTop": boolean; "changeThreshold": number;
/** Creates a new EditorConfig instance. */ /**
constructor($$source: Partial<EditorConfig> = {}) { * 最小保存间隔(毫秒)
*/
"minSaveInterval": number;
/** Creates a new EditingConfig instance. */
constructor($$source: Partial<EditingConfig> = {}) {
if (!("fontSize" in $$source)) { if (!("fontSize" in $$source)) {
this["fontSize"] = 0; this["fontSize"] = 0;
} }
@@ -316,22 +332,80 @@ export class EditorConfig {
if (!("tabType" in $$source)) { if (!("tabType" in $$source)) {
this["tabType"] = ("" as TabType); this["tabType"] = ("" as TabType);
} }
if (!("language" in $$source)) { if (!("autoSaveDelay" in $$source)) {
this["language"] = ("" as LanguageType); this["autoSaveDelay"] = 0;
} }
if (!("alwaysOnTop" in $$source)) { if (!("changeThreshold" in $$source)) {
this["alwaysOnTop"] = false; this["changeThreshold"] = 0;
}
if (!("minSaveInterval" in $$source)) {
this["minSaveInterval"] = 0;
} }
Object.assign(this, $$source); Object.assign(this, $$source);
} }
/** /**
* Creates a new EditorConfig instance from a string or object. * Creates a new EditingConfig instance from a string or object.
*/ */
static createFrom($$source: any = {}): EditorConfig { static createFrom($$source: any = {}): EditingConfig {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
return new EditorConfig($$parsedSource as Partial<EditorConfig>); return new EditingConfig($$parsedSource as Partial<EditingConfig>);
}
}
/**
* GeneralConfig 通用设置配置
*/
export class GeneralConfig {
/**
* 窗口是否置顶
*/
"alwaysOnTop": boolean;
/**
* 数据存储路径
*/
"dataPath": string;
/** Creates a new GeneralConfig instance. */
constructor($$source: Partial<GeneralConfig> = {}) {
if (!("alwaysOnTop" in $$source)) {
this["alwaysOnTop"] = false;
}
if (!("dataPath" in $$source)) {
this["dataPath"] = "";
}
Object.assign(this, $$source);
}
/**
* Creates a new GeneralConfig instance from a string or object.
*/
static createFrom($$source: any = {}): GeneralConfig {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
return new GeneralConfig($$parsedSource as Partial<GeneralConfig>);
}
}
/**
* KeyBindingsConfig 快捷键设置配置
*/
export class KeyBindingsConfig {
/** Creates a new KeyBindingsConfig instance. */
constructor($$source: Partial<KeyBindingsConfig> = {}) {
Object.assign(this, $$source);
}
/**
* Creates a new KeyBindingsConfig instance from a string or object.
*/
static createFrom($$source: any = {}): KeyBindingsConfig {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
return new KeyBindingsConfig($$parsedSource as Partial<KeyBindingsConfig>);
} }
} }
@@ -355,33 +429,6 @@ export enum LanguageType {
LangEnUS = "en-US", LangEnUS = "en-US",
}; };
/**
* PathsConfig 路径配置集合
*/
export class PathsConfig {
/**
* 数据存储路径
*/
"dataPath": string;
/** Creates a new PathsConfig instance. */
constructor($$source: Partial<PathsConfig> = {}) {
if (!("dataPath" in $$source)) {
this["dataPath"] = "";
}
Object.assign(this, $$source);
}
/**
* Creates a new PathsConfig instance from a string or object.
*/
static createFrom($$source: any = {}): PathsConfig {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
return new PathsConfig($$parsedSource as Partial<PathsConfig>);
}
}
/** /**
* TabType 定义了制表符类型 * TabType 定义了制表符类型
*/ */
@@ -402,9 +449,31 @@ export enum TabType {
TabTypeTab = "tab", TabTypeTab = "tab",
}; };
/**
* UpdatesConfig 更新设置配置
*/
export class UpdatesConfig {
/** Creates a new UpdatesConfig instance. */
constructor($$source: Partial<UpdatesConfig> = {}) {
Object.assign(this, $$source);
}
/**
* Creates a new UpdatesConfig instance from a string or object.
*/
static createFrom($$source: any = {}): UpdatesConfig {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
return new UpdatesConfig($$parsedSource as Partial<UpdatesConfig>);
}
}
// Private type creation functions // Private type creation functions
const $$createType0 = EditorConfig.createFrom; const $$createType0 = GeneralConfig.createFrom;
const $$createType1 = DocumentConfig.createFrom; const $$createType1 = EditingConfig.createFrom;
const $$createType2 = PathsConfig.createFrom; const $$createType2 = AppearanceConfig.createFrom;
const $$createType3 = ConfigMetadata.createFrom; const $$createType3 = KeyBindingsConfig.createFrom;
const $$createType4 = DocumentMeta.createFrom; const $$createType4 = UpdatesConfig.createFrom;
const $$createType5 = ConfigMetadata.createFrom;
const $$createType6 = DocumentMeta.createFrom;

View File

@@ -61,7 +61,7 @@ export function GetDiffInfo(oldText: string, newText: string): Promise<$models.D
/** /**
* GetSaveSettings 获取文档保存设置 * GetSaveSettings 获取文档保存设置
*/ */
export function GetSaveSettings(): Promise<models$0.DocumentConfig | null> & { cancel(): void } { export function GetSaveSettings(): Promise<models$0.EditingConfig | null> & { cancel(): void } {
let $resultPromise = $Call.ByID(4257471801) as any; let $resultPromise = $Call.ByID(4257471801) as any;
let $typingPromise = $resultPromise.then(($result: any) => { let $typingPromise = $resultPromise.then(($result: any) => {
return $$createType4($result); return $$createType4($result);
@@ -129,7 +129,7 @@ export function UpdateActiveDocumentContent(content: string): Promise<void> & {
/** /**
* UpdateSaveSettings 更新文档保存设置 * UpdateSaveSettings 更新文档保存设置
*/ */
export function UpdateSaveSettings(docConfig: models$0.DocumentConfig): Promise<void> & { cancel(): void } { export function UpdateSaveSettings(docConfig: models$0.EditingConfig): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(1245479534, docConfig) as any; let $resultPromise = $Call.ByID(1245479534, docConfig) as any;
return $resultPromise; return $resultPromise;
} }
@@ -138,5 +138,5 @@ export function UpdateSaveSettings(docConfig: models$0.DocumentConfig): Promise<
const $$createType0 = models$0.Document.createFrom; const $$createType0 = models$0.Document.createFrom;
const $$createType1 = $Create.Nullable($$createType0); const $$createType1 = $Create.Nullable($$createType0);
const $$createType2 = $models.DiffResult.createFrom; const $$createType2 = $models.DiffResult.createFrom;
const $$createType3 = models$0.DocumentConfig.createFrom; const $$createType3 = models$0.EditingConfig.createFrom;
const $$createType4 = $Create.Nullable($$createType3); const $$createType4 = $Create.Nullable($$createType3);

View File

@@ -1,75 +1,79 @@
<script setup lang="ts"> <script setup lang="ts">
import {useEditorStore} from '@/stores/editorStore';
import {useConfigStore, SUPPORTED_LOCALES, type SupportedLocaleType} from '@/stores/configStore';
import {useLogStore} from '@/stores/logStore';
import { useErrorHandler } from '@/utils/errorHandler';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { ref, onMounted, watch } from 'vue'; import { ref, onMounted, 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 * as runtime from '@wailsio/runtime';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
const editorStore = useEditorStore(); const editorStore = useEditorStore();
const configStore = useConfigStore(); const configStore = useConfigStore();
const logStore = useLogStore();
const { safeCall } = useErrorHandler(); const { safeCall } = useErrorHandler();
const { t, locale } = useI18n(); const { t, locale } = useI18n();
const router = useRouter(); const router = useRouter();
// 语言下拉菜单 // 语言下拉菜单
const showLanguageMenu = ref(false); const showLanguageMenu = ref(false);
// 切换语言 const supportedLanguages = [
const changeLanguage = async (localeCode: SupportedLocaleType) => { { code: 'zh-CN', name: '简体中文' },
await safeCall( { code: 'en-US', name: 'English' }
() => configStore.setLocale(localeCode), ];
'config.languageChangeFailed'
);
showLanguageMenu.value = false;
};
// 切换语言菜单显示
const toggleLanguageMenu = () => { const toggleLanguageMenu = () => {
showLanguageMenu.value = !showLanguageMenu.value; showLanguageMenu.value = !showLanguageMenu.value;
}; };
// 窗口置顶控制 const closeLanguageMenu = () => {
showLanguageMenu.value = false;
};
const changeLanguage = async (langCode: string) => {
await safeCall(() => configStore.setLanguage(langCode as any), 'language.changeFailed');
closeLanguageMenu();
};
// 设置窗口置顶
const setWindowAlwaysOnTop = async (isTop: boolean) => {
await safeCall(async () => {
await runtime.Window.SetAlwaysOnTop(isTop);
}, 'window.setTopFailed');
};
// 切换窗口置顶
const toggleAlwaysOnTop = async () => { const toggleAlwaysOnTop = async () => {
await safeCall(async () => { await safeCall(async () => {
await configStore.toggleAlwaysOnTop(); await configStore.toggleAlwaysOnTop();
// 使用Window.SetAlwaysOnTop方法设置窗口置顶状态 // 使用Window.SetAlwaysOnTop方法设置窗口置顶状态
await runtime.Window.SetAlwaysOnTop(configStore.config.alwaysOnTop); await runtime.Window.SetAlwaysOnTop(configStore.config.general.alwaysOnTop);
}, 'config.alwaysOnTopFailed'); }, 'config.alwaysOnTopFailed');
}; };
// 打开设置页面 // 跳转到设置页面
const openSettings = () => { const goToSettings = () => {
router.push('/settings'); router.push('/settings');
}; };
// 设置窗口置顶状态的通用函数 const isLoaded = ref(false);
const setWindowAlwaysOnTop = async (alwaysOnTop: boolean) => {
await safeCall(
() => runtime.Window.SetAlwaysOnTop(alwaysOnTop),
'config.alwaysOnTopFailed'
);
};
// 初始化配置 onMounted(() => {
onMounted(async () => { isLoaded.value = true;
// 加载配置
if (!configStore.configLoaded) {
await configStore.initConfig();
}
// 设置窗口置顶状态
if (configStore.config.alwaysOnTop) {
await setWindowAlwaysOnTop(true);
}
}); });
// 监听配置加载完成 // 监听置顶设置变化
watch(() => configStore.configLoaded, (isLoaded) => { watch(
if (isLoaded && configStore.config.alwaysOnTop) { () => configStore.config.general.alwaysOnTop,
setWindowAlwaysOnTop(true); async (newValue) => {
if (!isLoaded.value) return;
await runtime.Window.SetAlwaysOnTop(newValue);
}
);
// 在组件加载完成后应用置顶设置
watch(isLoaded, async (newLoaded) => {
if (newLoaded && configStore.config.general.alwaysOnTop) {
await setWindowAlwaysOnTop(true);
} }
}); });
</script> </script>
@@ -86,34 +90,30 @@ watch(() => configStore.configLoaded, (isLoaded) => {
<span class="stat-item" :title="t('toolbar.editor.selected')" v-if="editorStore.documentStats.selectedCharacters > 0"> <span class="stat-item" :title="t('toolbar.editor.selected')" v-if="editorStore.documentStats.selectedCharacters > 0">
{{ t('toolbar.editor.selected') }}: <span class="stat-value">{{ editorStore.documentStats.selectedCharacters }}</span> {{ t('toolbar.editor.selected') }}: <span class="stat-value">{{ editorStore.documentStats.selectedCharacters }}</span>
</span> </span>
<span v-if="logStore.showLog && logStore.latestLog" class="log-item" :class="'log-' + logStore.latestLog.level"
@click="logStore.hideCurrentLog()">
{{ logStore.latestLog.message }}
</span>
</div> </div>
<div class="actions"> <div class="actions">
<span class="font-size" :title="t('toolbar.fontSizeTooltip')" @click="() => configStore.resetFontSize()"> <span class="font-size" :title="t('toolbar.fontSizeTooltip')" @click="() => configStore.resetFontSize()">
{{ configStore.config.fontSize }}px {{ configStore.config.editing.fontSize }}px
</span> </span>
<span class="tab-settings"> <span class="tab-settings">
<label :title="t('toolbar.tabLabel')" class="tab-toggle"> <label :title="t('toolbar.tabLabel')" class="tab-toggle">
<input type="checkbox" :checked="configStore.config.enableTabIndent" @change="() => configStore.toggleTabIndent()"/> <input type="checkbox" :checked="configStore.config.editing.enableTabIndent" @change="() => configStore.toggleTabIndent()"/>
<span>{{ t('toolbar.tabLabel') }}</span> <span>{{ t('toolbar.tabLabel') }}</span>
</label> </label>
<span class="tab-type" :title="t('toolbar.tabType.' + (configStore.config.tabType === 'spaces' ? 'spaces' : 'tab'))" @click="() => configStore.toggleTabType()"> <span class="tab-type" :title="t('toolbar.tabType.' + (configStore.config.editing.tabType === 'spaces' ? 'spaces' : 'tab'))" @click="() => configStore.toggleTabType()">
{{ t('toolbar.tabType.' + (configStore.config.tabType === 'spaces' ? 'spaces' : 'tab')) }} {{ t('toolbar.tabType.' + (configStore.config.editing.tabType === 'spaces' ? 'spaces' : 'tab')) }}
</span> </span>
<span class="tab-size" title="Tab大小" v-if="configStore.config.tabType === 'spaces'"> <span class="tab-size" title="Tab大小" v-if="configStore.config.editing.tabType === 'spaces'">
<button class="tab-btn" @click="() => configStore.decreaseTabSize()" :disabled="configStore.config.tabSize <= configStore.tabSize.min">-</button> <button class="tab-btn" @click="() => configStore.decreaseTabSize()" :disabled="configStore.config.editing.tabSize <= configStore.tabSize.min">-</button>
<span>{{ configStore.config.tabSize }}</span> <span>{{ configStore.config.editing.tabSize }}</span>
<button class="tab-btn" @click="() => configStore.increaseTabSize()" :disabled="configStore.config.tabSize >= configStore.tabSize.max">+</button> <button class="tab-btn" @click="() => configStore.increaseTabSize()" :disabled="configStore.config.editing.tabSize >= configStore.tabSize.max">+</button>
</span> </span>
</span> </span>
<!-- 窗口置顶图标按钮 --> <!-- 窗口置顶图标按钮 -->
<div <div
class="pin-button" class="pin-button"
:class="{ 'active': configStore.config.alwaysOnTop }" :class="{ 'active': configStore.config.general.alwaysOnTop }"
:title="t('toolbar.alwaysOnTop')" :title="t('toolbar.alwaysOnTop')"
@click="toggleAlwaysOnTop" @click="toggleAlwaysOnTop"
> >
@@ -130,7 +130,7 @@ watch(() => configStore.configLoaded, (isLoaded) => {
</button> </button>
<div class="selector-menu" v-if="showLanguageMenu"> <div class="selector-menu" v-if="showLanguageMenu">
<div <div
v-for="lang in SUPPORTED_LOCALES" v-for="lang in supportedLanguages"
:key="lang.code" :key="lang.code"
class="selector-option" class="selector-option"
:class="{ active: locale === lang.code }" :class="{ active: locale === lang.code }"
@@ -141,7 +141,7 @@ watch(() => configStore.configLoaded, (isLoaded) => {
</div> </div>
</div> </div>
<button class="settings-btn" :title="t('toolbar.settings')" @click="openSettings"> <button class="settings-btn" :title="t('toolbar.settings')" @click="goToSettings">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="3"></circle> <circle cx="12" cy="12" r="3"></circle>
@@ -177,24 +177,6 @@ watch(() => configStore.configLoaded, (isLoaded) => {
color: #e0e0e0; color: #e0e0e0;
} }
} }
.log-item {
cursor: default;
font-size: 12px;
transition: opacity 0.3s ease;
&.log-info {
color: rgba(177, 176, 176, 0.8);
}
&.log-warning {
color: rgba(240, 230, 140, 0.8);
}
&.log-error {
color: rgba(255, 107, 107, 0.8);
}
}
} }
.actions { .actions {

View File

@@ -3,7 +3,7 @@ import {computed, reactive} from 'vue';
import { import {
ConfigService ConfigService
} from '@/../bindings/voidraft/internal/services'; } from '@/../bindings/voidraft/internal/services';
import {EditorConfig, TabType, LanguageType} from '@/../bindings/voidraft/internal/models/models'; import {AppConfig, GeneralConfig, EditingConfig, AppearanceConfig, TabType, LanguageType} from '@/../bindings/voidraft/internal/models';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useErrorHandler } from '@/utils/errorHandler'; import { useErrorHandler } from '@/utils/errorHandler';
import { ConfigUtils } from '@/utils/configUtils'; import { ConfigUtils } from '@/utils/configUtils';
@@ -24,26 +24,41 @@ export const SUPPORTED_LOCALES = [
] as const; ] as const;
// 配置键映射和限制的类型定义 // 配置键映射和限制的类型定义
type ConfigKeyMap = { type GeneralConfigKeyMap = {
readonly [K in keyof EditorConfig]: string; readonly [K in keyof GeneralConfig]: string;
};
type EditingConfigKeyMap = {
readonly [K in keyof EditingConfig]: string;
};
type AppearanceConfigKeyMap = {
readonly [K in keyof AppearanceConfig]: string;
}; };
type NumberConfigKey = 'fontSize' | 'tabSize' | 'lineHeight'; type NumberConfigKey = 'fontSize' | 'tabSize' | 'lineHeight';
type StringConfigKey = 'fontFamily' | 'fontWeight';
type BooleanConfigKey = 'enableTabIndent' | 'alwaysOnTop';
type EnumConfigKey = 'tabType' | 'language';
// 配置键映射 // 配置键映射
const CONFIG_KEY_MAP: ConfigKeyMap = { const GENERAL_CONFIG_KEY_MAP: GeneralConfigKeyMap = {
fontSize: 'editor.font_size', alwaysOnTop: 'general.always_on_top',
fontFamily: 'editor.font_family', dataPath: 'general.data_path'
fontWeight: 'editor.font_weight', } as const;
lineHeight: 'editor.line_height',
enableTabIndent: 'editor.enable_tab_indent', const EDITING_CONFIG_KEY_MAP: EditingConfigKeyMap = {
tabSize: 'editor.tab_size', fontSize: 'editing.font_size',
tabType: 'editor.tab_type', fontFamily: 'editing.font_family',
language: 'editor.language', fontWeight: 'editing.font_weight',
alwaysOnTop: 'editor.always_on_top' lineHeight: 'editing.line_height',
enableTabIndent: 'editing.enable_tab_indent',
tabSize: 'editing.tab_size',
tabType: 'editing.tab_type',
autoSaveDelay: 'editing.auto_save_delay',
changeThreshold: 'editing.change_threshold',
minSaveInterval: 'editing.min_save_interval'
} as const;
const APPEARANCE_CONFIG_KEY_MAP: AppearanceConfigKeyMap = {
language: 'appearance.language'
} as const; } as const;
// 配置限制 // 配置限制
@@ -80,7 +95,12 @@ const getBrowserLanguage = (): SupportedLocaleType => {
}; };
// 默认配置 // 默认配置
const DEFAULT_CONFIG: EditorConfig = { const DEFAULT_CONFIG: AppConfig = {
general: {
alwaysOnTop: false,
dataPath: './data'
},
editing: {
fontSize: CONFIG_LIMITS.fontSize.default, fontSize: CONFIG_LIMITS.fontSize.default,
fontFamily: FONT_OPTIONS[0].value, fontFamily: FONT_OPTIONS[0].value,
fontWeight: 'normal', fontWeight: 'normal',
@@ -88,8 +108,19 @@ const DEFAULT_CONFIG: EditorConfig = {
enableTabIndent: true, enableTabIndent: true,
tabSize: CONFIG_LIMITS.tabSize.default, tabSize: CONFIG_LIMITS.tabSize.default,
tabType: CONFIG_LIMITS.tabType.default, tabType: CONFIG_LIMITS.tabType.default,
language: LanguageType.LangZhCN, autoSaveDelay: 5000,
alwaysOnTop: false changeThreshold: 500,
minSaveInterval: 1000
},
appearance: {
language: LanguageType.LangZhCN
},
keyBindings: {},
updates: {},
metadata: {
version: '1.0.0',
lastUpdated: null
}
}; };
export const useConfigStore = defineStore('config', () => { export const useConfigStore = defineStore('config', () => {
@@ -98,7 +129,7 @@ export const useConfigStore = defineStore('config', () => {
// 响应式状态 // 响应式状态
const state = reactive({ const state = reactive({
config: { ...DEFAULT_CONFIG } as EditorConfig, config: { ...DEFAULT_CONFIG } as AppConfig,
isLoading: false, isLoading: false,
configLoaded: false configLoaded: false
}); });
@@ -110,19 +141,49 @@ export const useConfigStore = defineStore('config', () => {
) as Record<NumberConfigKey, ReturnType<typeof createLimitComputed>>; ) as Record<NumberConfigKey, ReturnType<typeof createLimitComputed>>;
// 通用配置更新方法 // 通用配置更新方法
const updateConfig = async <K extends keyof EditorConfig>(key: K, value: EditorConfig[K]): Promise<void> => { const updateGeneralConfig = async <K extends keyof GeneralConfig>(key: K, value: GeneralConfig[K]): Promise<void> => {
// 确保配置已加载 // 确保配置已加载
if (!state.configLoaded && !state.isLoading) { if (!state.configLoaded && !state.isLoading) {
await initConfig(); await initConfig();
} }
const backendKey = CONFIG_KEY_MAP[key]; const backendKey = GENERAL_CONFIG_KEY_MAP[key];
if (!backendKey) { if (!backendKey) {
throw new Error(`No backend key mapping found for ${key.toString()}`); throw new Error(`No backend key mapping found for general.${key.toString()}`);
} }
await ConfigService.Set(backendKey, value); await ConfigService.Set(backendKey, value);
state.config[key] = value; state.config.general[key] = value;
};
const updateEditingConfig = async <K extends keyof EditingConfig>(key: K, value: EditingConfig[K]): Promise<void> => {
// 确保配置已加载
if (!state.configLoaded && !state.isLoading) {
await initConfig();
}
const backendKey = EDITING_CONFIG_KEY_MAP[key];
if (!backendKey) {
throw new Error(`No backend key mapping found for editing.${key.toString()}`);
}
await ConfigService.Set(backendKey, value);
state.config.editing[key] = value;
};
const updateAppearanceConfig = async <K extends keyof AppearanceConfig>(key: K, value: AppearanceConfig[K]): Promise<void> => {
// 确保配置已加载
if (!state.configLoaded && !state.isLoading) {
await initConfig();
}
const backendKey = APPEARANCE_CONFIG_KEY_MAP[key];
if (!backendKey) {
throw new Error(`No backend key mapping found for appearance.${key.toString()}`);
}
await ConfigService.Set(backendKey, value);
state.config.appearance[key] = value;
}; };
// 加载配置 // 加载配置
@@ -133,8 +194,14 @@ export const useConfigStore = defineStore('config', () => {
try { try {
const appConfig = await ConfigService.GetConfig(); const appConfig = await ConfigService.GetConfig();
if (appConfig?.editor) { if (appConfig) {
Object.assign(state.config, appConfig.editor); // 合并配置
if (appConfig.general) Object.assign(state.config.general, appConfig.general);
if (appConfig.editing) Object.assign(state.config.editing, appConfig.editing);
if (appConfig.appearance) Object.assign(state.config.appearance, appConfig.appearance);
if (appConfig.keyBindings) Object.assign(state.config.keyBindings, appConfig.keyBindings);
if (appConfig.updates) Object.assign(state.config.updates, appConfig.updates);
if (appConfig.metadata) Object.assign(state.config.metadata, appConfig.metadata);
} }
state.configLoaded = true; state.configLoaded = true;
@@ -149,23 +216,26 @@ export const useConfigStore = defineStore('config', () => {
const clamp = (value: number) => ConfigUtils.clamp(value, limit.min, limit.max); const clamp = (value: number) => ConfigUtils.clamp(value, limit.min, limit.max);
return { return {
increase: () => safeCall(() => updateConfig(key, clamp(state.config[key] + 1)), 'config.saveFailed', 'config.saveSuccess'), increase: () => safeCall(() => updateEditingConfig(key, clamp(state.config.editing[key] + 1)), 'config.saveFailed', 'config.saveSuccess'),
decrease: () => safeCall(() => updateConfig(key, clamp(state.config[key] - 1)), 'config.saveFailed', 'config.saveSuccess'), decrease: () => safeCall(() => updateEditingConfig(key, clamp(state.config.editing[key] - 1)), 'config.saveFailed', 'config.saveSuccess'),
set: (value: number) => safeCall(() => updateConfig(key, clamp(value)), 'config.saveFailed', 'config.saveSuccess'), set: (value: number) => safeCall(() => updateEditingConfig(key, clamp(value)), 'config.saveFailed', 'config.saveSuccess'),
reset: () => safeCall(() => updateConfig(key, limit.default), 'config.saveFailed', 'config.saveSuccess') reset: () => safeCall(() => updateEditingConfig(key, limit.default), 'config.saveFailed', 'config.saveSuccess')
}; };
}; };
// 通用布尔值切换器 // 通用布尔值切换器
const createToggler = <T extends BooleanConfigKey>(key: T) => const createGeneralToggler = <T extends keyof GeneralConfig>(key: T) =>
() => safeCall(() => updateConfig(key, !state.config[key]), 'config.saveFailed', 'config.saveSuccess'); () => safeCall(() => updateGeneralConfig(key, !state.config.general[key] as GeneralConfig[T]), 'config.saveFailed', 'config.saveSuccess');
const createEditingToggler = <T extends keyof EditingConfig>(key: T) =>
() => safeCall(() => updateEditingConfig(key, !state.config.editing[key] as EditingConfig[T]), 'config.saveFailed', 'config.saveSuccess');
// 枚举值切换器 // 枚举值切换器
const createEnumToggler = <T extends TabType>(key: 'tabType', values: readonly T[]) => const createEnumToggler = <T extends TabType>(key: 'tabType', values: readonly T[]) =>
() => { () => {
const currentIndex = values.indexOf(state.config[key] as T); const currentIndex = values.indexOf(state.config.editing[key] as T);
const nextIndex = (currentIndex + 1) % values.length; const nextIndex = (currentIndex + 1) % values.length;
return safeCall(() => updateConfig(key, values[nextIndex]), 'config.saveFailed', 'config.saveSuccess'); return safeCall(() => updateEditingConfig(key, values[nextIndex]), 'config.saveFailed', 'config.saveSuccess');
}; };
// 重置配置 // 重置配置
@@ -184,8 +254,7 @@ export const useConfigStore = defineStore('config', () => {
// 语言设置方法 // 语言设置方法
const setLanguage = async (language: LanguageType): Promise<void> => { const setLanguage = async (language: LanguageType): Promise<void> => {
await safeCall(async () => { await safeCall(async () => {
await ConfigService.Set(CONFIG_KEY_MAP.language, language); await updateAppearanceConfig('language', language);
state.config.language = language;
// 同步更新前端语言 // 同步更新前端语言
const frontendLocale = ConfigUtils.backendLanguageToFrontend(language); const frontendLocale = ConfigUtils.backendLanguageToFrontend(language);
@@ -193,12 +262,6 @@ export const useConfigStore = defineStore('config', () => {
}, 'config.languageChangeFailed', 'config.languageChanged'); }, 'config.languageChangeFailed', 'config.languageChanged');
}; };
// 通过前端语言代码设置语言
const setLocale = async (localeCode: SupportedLocaleType): Promise<void> => {
const backendLanguage = ConfigUtils.frontendLanguageToBackend(localeCode);
await setLanguage(backendLanguage);
};
// 初始化语言设置 // 初始化语言设置
const initializeLanguage = async (): Promise<void> => { const initializeLanguage = async (): Promise<void> => {
try { try {
@@ -208,7 +271,7 @@ export const useConfigStore = defineStore('config', () => {
} }
// 同步前端语言设置 // 同步前端语言设置
const frontendLocale = ConfigUtils.backendLanguageToFrontend(state.config.language); const frontendLocale = ConfigUtils.backendLanguageToFrontend(state.config.appearance.language);
locale.value = frontendLocale as any; locale.value = frontendLocale as any;
} catch (error) { } catch (error) {
const browserLang = getBrowserLanguage(); const browserLang = getBrowserLanguage();
@@ -225,15 +288,16 @@ export const useConfigStore = defineStore('config', () => {
// 创建切换器实例 // 创建切换器实例
const togglers = { const togglers = {
tabIndent: createToggler('enableTabIndent'), tabIndent: createEditingToggler('enableTabIndent'),
alwaysOnTop: createToggler('alwaysOnTop'), alwaysOnTop: createGeneralToggler('alwaysOnTop'),
tabType: createEnumToggler('tabType', CONFIG_LIMITS.tabType.values) tabType: createEnumToggler('tabType', CONFIG_LIMITS.tabType.values)
}; };
// 字符串配置设置器 // 字符串配置设置器
const setters = { const setters = {
fontFamily: (value: string) => safeCall(() => updateConfig('fontFamily', value), 'config.saveFailed', 'config.saveSuccess'), fontFamily: (value: string) => safeCall(() => updateEditingConfig('fontFamily', value), 'config.saveFailed', 'config.saveSuccess'),
fontWeight: (value: string) => safeCall(() => updateConfig('fontWeight', 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')
}; };
return { return {
@@ -248,11 +312,9 @@ export const useConfigStore = defineStore('config', () => {
// 核心方法 // 核心方法
initConfig: () => safeCall(() => initConfig(), 'config.loadFailed', 'config.loadSuccess'), initConfig: () => safeCall(() => initConfig(), 'config.loadFailed', 'config.loadSuccess'),
resetConfig, resetConfig,
updateConfig: (key: keyof EditorConfig, value: any) => safeCall(() => updateConfig(key, value), 'config.saveFailed', 'config.saveSuccess'),
// 语言相关方法 // 语言相关方法
setLanguage, setLanguage,
setLocale,
initializeLanguage, initializeLanguage,
// 字体大小操作 // 字体大小操作
@@ -279,6 +341,9 @@ export const useConfigStore = defineStore('config', () => {
// 字体操作 // 字体操作
setFontFamily: setters.fontFamily, setFontFamily: setters.fontFamily,
setFontWeight: setters.fontWeight, setFontWeight: setters.fontWeight,
// 路径操作
setDataPath: setters.dataPath,
}; };
},{ },{
persist: true, persist: true,

View File

@@ -33,7 +33,7 @@ export const useEditorStore = defineStore('editor', () => {
// 更新编辑器的字体大小 // 更新编辑器的字体大小
const editorDOM = editorView.value.dom; const editorDOM = editorView.value.dom;
if (editorDOM) { if (editorDOM) {
editorDOM.style.fontSize = `${configStore.config.fontSize}px`; editorDOM.style.fontSize = `${configStore.config.editing.fontSize}px`;
editorView.value?.requestMeasure(); editorView.value?.requestMeasure();
} }
} }

View File

@@ -53,17 +53,17 @@ const createEditor = async () => {
// 获取Tab相关扩展 // 获取Tab相关扩展
const tabExtensions = getTabExtensions( const tabExtensions = getTabExtensions(
configStore.config.tabSize, configStore.config.editing.tabSize,
configStore.config.enableTabIndent, configStore.config.editing.enableTabIndent,
configStore.config.tabType configStore.config.editing.tabType
); );
// 创建字体扩展 // 创建字体扩展
const fontExtension = createFontExtensionFromBackend({ const fontExtension = createFontExtensionFromBackend({
fontFamily: configStore.config.fontFamily, fontFamily: configStore.config.editing.fontFamily,
fontSize: configStore.config.fontSize, fontSize: configStore.config.editing.fontSize,
lineHeight: configStore.config.lineHeight, lineHeight: configStore.config.editing.lineHeight,
fontWeight: configStore.config.fontWeight fontWeight: configStore.config.editing.fontWeight
}); });
// 创建统计信息更新扩展 // 创建统计信息更新扩展
@@ -148,9 +148,9 @@ const reconfigureTabSettings = () => {
if (!editorStore.editorView) return; if (!editorStore.editorView) return;
updateTabConfig( updateTabConfig(
editorStore.editorView as EditorView, editorStore.editorView as EditorView,
configStore.config.tabSize, configStore.config.editing.tabSize,
configStore.config.enableTabIndent, configStore.config.editing.enableTabIndent,
configStore.config.tabType configStore.config.editing.tabType
); );
}; };
@@ -158,33 +158,33 @@ const reconfigureTabSettings = () => {
const reconfigureFontSettings = () => { const reconfigureFontSettings = () => {
if (!editorStore.editorView) return; if (!editorStore.editorView) return;
updateFontConfig(editorStore.editorView as EditorView, { updateFontConfig(editorStore.editorView as EditorView, {
fontFamily: configStore.config.fontFamily, fontFamily: configStore.config.editing.fontFamily,
fontSize: configStore.config.fontSize, fontSize: configStore.config.editing.fontSize,
lineHeight: configStore.config.lineHeight, lineHeight: configStore.config.editing.lineHeight,
fontWeight: configStore.config.fontWeight fontWeight: configStore.config.editing.fontWeight
}); });
}; };
// 监听Tab设置变化 // 监听Tab设置变化
watch(() => configStore.config.tabSize, reconfigureTabSettings); watch([
watch(() => configStore.config.enableTabIndent, reconfigureTabSettings); () => configStore.config.editing.tabSize,
watch(() => configStore.config.tabType, reconfigureTabSettings); () => configStore.config.editing.enableTabIndent,
() => configStore.config.editing.tabType,
], () => {
reconfigureTabSettings();
});
// 监听字体大小变化 // 监听字体大小变化
watch(() => configStore.config.fontSize, () => { watch([
() => configStore.config.editing.fontFamily,
() => configStore.config.editing.fontSize,
() => configStore.config.editing.lineHeight,
() => configStore.config.editing.fontWeight,
], () => {
reconfigureFontSettings(); reconfigureFontSettings();
editorStore.applyFontSize(); editorStore.applyFontSize();
}); });
// 监听字体族变化
watch(() => configStore.config.fontFamily, reconfigureFontSettings);
// 监听字体粗细变化
watch(() => configStore.config.fontWeight, reconfigureFontSettings);
// 监听行高变化
watch(() => configStore.config.lineHeight, reconfigureFontSettings);
onMounted(() => { onMounted(() => {
// 创建编辑器 // 创建编辑器
createEditor(); createEditor();

View File

@@ -47,7 +47,7 @@ const selectTheme = (themeId: string) => {
<div class="settings-page"> <div class="settings-page">
<SettingSection :title="t('settings.language')"> <SettingSection :title="t('settings.language')">
<SettingItem :title="t('settings.language')" :description="t('settings.restartRequired')"> <SettingItem :title="t('settings.language')" :description="t('settings.restartRequired')">
<select class="select-input" :value="configStore.config.language" @change="updateLanguage"> <select class="select-input" :value="configStore.config.appearance.language" @change="updateLanguage">
<option v-for="option in languageOptions" :key="option.value" :value="option.value"> <option v-for="option in languageOptions" :key="option.value" :value="option.value">
{{ option.label }} {{ option.label }}
</option> </option>

View File

@@ -22,7 +22,7 @@ onMounted(async () => {
// 字体选择选项 // 字体选择选项
const fontFamilyOptions = FONT_OPTIONS; const fontFamilyOptions = FONT_OPTIONS;
const currentFontFamily = computed(() => configStore.config.fontFamily); const currentFontFamily = computed(() => configStore.config.editing.fontFamily);
// 字体选择 // 字体选择
const handleFontFamilyChange = async (event: Event) => { const handleFontFamilyChange = async (event: Event) => {
@@ -60,7 +60,7 @@ const handleFontWeightChange = async (event: Event) => {
// 行高控制 // 行高控制
const increaseLineHeight = async () => { const increaseLineHeight = async () => {
const newLineHeight = Math.min(3.0, configStore.config.lineHeight + 0.1); const newLineHeight = Math.min(3.0, configStore.config.editing.lineHeight + 0.1);
await safeCall( await safeCall(
() => configStore.setLineHeight(Math.round(newLineHeight * 10) / 10), () => configStore.setLineHeight(Math.round(newLineHeight * 10) / 10),
'config.lineHeightIncreaseFailed' 'config.lineHeightIncreaseFailed'
@@ -68,7 +68,7 @@ const increaseLineHeight = async () => {
}; };
const decreaseLineHeight = async () => { const decreaseLineHeight = async () => {
const newLineHeight = Math.max(1.0, configStore.config.lineHeight - 0.1); const newLineHeight = Math.max(1.0, configStore.config.editing.lineHeight - 0.1);
await safeCall( await safeCall(
() => configStore.setLineHeight(Math.round(newLineHeight * 10) / 10), () => configStore.setLineHeight(Math.round(newLineHeight * 10) / 10),
'config.lineHeightDecreaseFailed' 'config.lineHeightDecreaseFailed'
@@ -92,7 +92,7 @@ const decreaseFontSize = async () => {
// Tab类型切换 // Tab类型切换
const tabTypeText = computed(() => { const tabTypeText = computed(() => {
return configStore.config.tabType === TabType.TabTypeSpaces return configStore.config.editing.tabType === TabType.TabTypeSpaces
? t('settings.spaces') ? t('settings.spaces')
: t('settings.tabs'); : t('settings.tabs');
}); });
@@ -156,7 +156,7 @@ const handleToggleTabType = async () => {
> >
<div class="number-control"> <div class="number-control">
<button @click="decreaseFontSize" class="control-button">-</button> <button @click="decreaseFontSize" class="control-button">-</button>
<span>{{ configStore.config.fontSize }}px</span> <span>{{ configStore.config.editing.fontSize }}px</span>
<button @click="increaseFontSize" class="control-button">+</button> <button @click="increaseFontSize" class="control-button">+</button>
</div> </div>
</SettingItem> </SettingItem>
@@ -167,7 +167,7 @@ const handleToggleTabType = async () => {
> >
<select <select
class="font-weight-select" class="font-weight-select"
:value="configStore.config.fontWeight" :value="configStore.config.editing.fontWeight"
@change="handleFontWeightChange" @change="handleFontWeightChange"
> >
<option <option
@@ -186,16 +186,16 @@ const handleToggleTabType = async () => {
> >
<div class="number-control"> <div class="number-control">
<button @click="decreaseLineHeight" class="control-button">-</button> <button @click="decreaseLineHeight" class="control-button">-</button>
<span>{{ configStore.config.lineHeight.toFixed(1) }}</span> <span>{{ configStore.config.editing.lineHeight.toFixed(1) }}</span>
<button @click="increaseLineHeight" class="control-button">+</button> <button @click="increaseLineHeight" class="control-button">+</button>
</div> </div>
</SettingItem> </SettingItem>
<div class="font-preview" :style="{ <div class="font-preview" :style="{
fontSize: `${configStore.config.fontSize}px`, fontSize: `${configStore.config.editing.fontSize}px`,
fontFamily: configStore.config.fontFamily, fontFamily: configStore.config.editing.fontFamily,
fontWeight: configStore.config.fontWeight, fontWeight: configStore.config.editing.fontWeight,
lineHeight: configStore.config.lineHeight lineHeight: configStore.config.editing.lineHeight
}"> }">
<div class="preview-label">字体预览</div> <div class="preview-label">字体预览</div>
<div class="preview-text"> <div class="preview-text">
@@ -210,9 +210,9 @@ const handleToggleTabType = async () => {
<SettingSection :title="t('settings.tabSettings')"> <SettingSection :title="t('settings.tabSettings')">
<SettingItem :title="t('settings.tabSize')"> <SettingItem :title="t('settings.tabSize')">
<div class="number-control"> <div class="number-control">
<button @click="decreaseTabSize" class="control-button" :disabled="configStore.config.tabSize <= configStore.tabSize.min">-</button> <button @click="decreaseTabSize" class="control-button" :disabled="configStore.config.editing.tabSize <= configStore.tabSize.min">-</button>
<span>{{ configStore.config.tabSize }}</span> <span>{{ configStore.config.editing.tabSize }}</span>
<button @click="increaseTabSize" class="control-button" :disabled="configStore.config.tabSize >= configStore.tabSize.max">+</button> <button @click="increaseTabSize" class="control-button" :disabled="configStore.config.editing.tabSize >= configStore.tabSize.max">+</button>
</div> </div>
</SettingItem> </SettingItem>
@@ -224,7 +224,7 @@ const handleToggleTabType = async () => {
<SettingItem :title="t('settings.enableTabIndent')"> <SettingItem :title="t('settings.enableTabIndent')">
<ToggleSwitch <ToggleSwitch
v-model="configStore.config.enableTabIndent" v-model="configStore.config.editing.enableTabIndent"
@update:modelValue="handleToggleTabIndent" @update:modelValue="handleToggleTabIndent"
/> />
</SettingItem> </SettingItem>

View File

@@ -52,7 +52,7 @@ const resetSettings = async () => {
<div class="settings-page"> <div class="settings-page">
<SettingSection :title="t('settings.globalHotkey')"> <SettingSection :title="t('settings.globalHotkey')">
<SettingItem :title="t('settings.enableGlobalHotkey')"> <SettingItem :title="t('settings.enableGlobalHotkey')">
<ToggleSwitch v-model="configStore.config.alwaysOnTop" /> <!-- 此处使用alwaysOnTop作为示例 --> <ToggleSwitch v-model="configStore.config.general.alwaysOnTop" /> <!-- 此处使用alwaysOnTop作为示例 -->
</SettingItem> </SettingItem>
<div class="hotkey-selector"> <div class="hotkey-selector">
@@ -87,19 +87,19 @@ const resetSettings = async () => {
<SettingSection :title="t('settings.window')"> <SettingSection :title="t('settings.window')">
<SettingItem :title="t('settings.showInSystemTray')"> <SettingItem :title="t('settings.showInSystemTray')">
<ToggleSwitch v-model="configStore.config.alwaysOnTop" /> <!-- 需要后端实现 --> <ToggleSwitch v-model="configStore.config.general.alwaysOnTop" /> <!-- 需要后端实现 -->
</SettingItem> </SettingItem>
<SettingItem :title="t('settings.alwaysOnTop')"> <SettingItem :title="t('settings.alwaysOnTop')">
<ToggleSwitch v-model="configStore.config.alwaysOnTop" @update:modelValue="configStore.toggleAlwaysOnTop" /> <ToggleSwitch v-model="configStore.config.general.alwaysOnTop" @update:modelValue="configStore.toggleAlwaysOnTop" />
</SettingItem> </SettingItem>
</SettingSection> </SettingSection>
<SettingSection :title="t('settings.bufferFiles')"> <SettingSection :title="t('settings.bufferFiles')">
<SettingItem :title="t('settings.useCustomLocation')"> <SettingItem :title="t('settings.useCustomLocation')">
<ToggleSwitch v-model="configStore.config.alwaysOnTop" /> <!-- 需要后端实现 --> <ToggleSwitch v-model="configStore.config.general.alwaysOnTop" /> <!-- 需要后端实现 -->
</SettingItem> </SettingItem>
<div class="directory-selector"> <div class="directory-selector">
<div class="path-display">{{ configStore.config.alwaysOnTop ? 'C:/Custom/Path' : 'Default Location' }}</div> <div class="path-display">{{ configStore.config.general.alwaysOnTop ? 'C:/Custom/Path' : 'Default Location' }}</div>
<button class="select-button">{{ t('settings.selectDirectory') }}</button> <button class="select-button">{{ t('settings.selectDirectory') }}</button>
</div> </div>
</SettingSection> </SettingSection>

View File

@@ -16,29 +16,6 @@ const (
TabTypeTab TabType = "tab" TabTypeTab TabType = "tab"
) )
// DocumentConfig 定义文档配置
type DocumentConfig struct {
// 自动保存延迟(毫秒)- 内容变更后多久自动保存
AutoSaveDelay int `json:"autoSaveDelay" yaml:"auto_save_delay" mapstructure:"auto_save_delay"`
// 变更字符阈值,超过此阈值立即触发保存
ChangeThreshold int `json:"changeThreshold" yaml:"change_threshold" mapstructure:"change_threshold"`
// 最小保存间隔(毫秒)- 两次保存之间的最小时间间隔避免频繁IO
MinSaveInterval int `json:"minSaveInterval" yaml:"min_save_interval" mapstructure:"min_save_interval"`
}
// EditorConfig 定义编辑器配置
type EditorConfig struct {
FontSize int `json:"fontSize" yaml:"font_size" mapstructure:"font_size"` // 字体大小
FontFamily string `json:"fontFamily" yaml:"font_family" mapstructure:"font_family"` // 字体族
FontWeight string `json:"fontWeight" yaml:"font_weight" mapstructure:"font_weight"` // 字体粗细
LineHeight float64 `json:"lineHeight" yaml:"line_height" mapstructure:"line_height"` // 行高
EnableTabIndent bool `json:"enableTabIndent" yaml:"enable_tab_indent" mapstructure:"enable_tab_indent"` // 是否启用Tab缩进
TabSize int `json:"tabSize" yaml:"tab_size" mapstructure:"tab_size"` // Tab大小
TabType TabType `json:"tabType" yaml:"tab_type" mapstructure:"tab_type"` // Tab类型空格或Tab
Language LanguageType `json:"language" yaml:"language" mapstructure:"language"` // 界面语言
AlwaysOnTop bool `json:"alwaysOnTop" yaml:"always_on_top" mapstructure:"always_on_top"` // 窗口是否置顶
}
// LanguageType 语言类型定义 // LanguageType 语言类型定义
type LanguageType string type LanguageType string
@@ -49,16 +26,53 @@ const (
LangEnUS LanguageType = "en-US" LangEnUS LanguageType = "en-US"
) )
// PathsConfig 路径配置集合 // GeneralConfig 通用设置配置
type PathsConfig struct { type GeneralConfig struct {
AlwaysOnTop bool `json:"alwaysOnTop" yaml:"always_on_top" mapstructure:"always_on_top"` // 窗口是否置顶
DataPath string `json:"dataPath" yaml:"data_path" mapstructure:"data_path"` // 数据存储路径 DataPath string `json:"dataPath" yaml:"data_path" mapstructure:"data_path"` // 数据存储路径
} }
// AppConfig 应用配置 - 包含业务配置和路径配置 // EditingConfig 编辑设置配置
type EditingConfig struct {
// 字体设置
FontSize int `json:"fontSize" yaml:"font_size" mapstructure:"font_size"` // 字体大小
FontFamily string `json:"fontFamily" yaml:"font_family" mapstructure:"font_family"` // 字体族
FontWeight string `json:"fontWeight" yaml:"font_weight" mapstructure:"font_weight"` // 字体粗细
LineHeight float64 `json:"lineHeight" yaml:"line_height" mapstructure:"line_height"` // 行高
// Tab设置
EnableTabIndent bool `json:"enableTabIndent" yaml:"enable_tab_indent" mapstructure:"enable_tab_indent"` // 是否启用Tab缩进
TabSize int `json:"tabSize" yaml:"tab_size" mapstructure:"tab_size"` // Tab大小
TabType TabType `json:"tabType" yaml:"tab_type" mapstructure:"tab_type"` // Tab类型空格或Tab
// 保存选项
AutoSaveDelay int `json:"autoSaveDelay" yaml:"auto_save_delay" mapstructure:"auto_save_delay"` // 自动保存延迟(毫秒)
ChangeThreshold int `json:"changeThreshold" yaml:"change_threshold" mapstructure:"change_threshold"` // 变更字符阈值
MinSaveInterval int `json:"minSaveInterval" yaml:"min_save_interval" mapstructure:"min_save_interval"` // 最小保存间隔(毫秒)
}
// AppearanceConfig 外观设置配置
type AppearanceConfig struct {
Language LanguageType `json:"language" yaml:"language" mapstructure:"language"` // 界面语言
}
// KeyBindingsConfig 快捷键设置配置
type KeyBindingsConfig struct {
// 预留给未来的快捷键配置
}
// UpdatesConfig 更新设置配置
type UpdatesConfig struct {
// 预留给未来的更新配置
}
// AppConfig 应用配置 - 按照前端设置页面分类组织
type AppConfig struct { type AppConfig struct {
Editor EditorConfig `json:"editor" yaml:"editor" mapstructure:"editor"` // 编辑器配 General GeneralConfig `json:"general" yaml:"general" mapstructure:"general"` // 通用设
Document DocumentConfig `json:"document" yaml:"document" mapstructure:"document"` // 文档配 Editing EditingConfig `json:"editing" yaml:"editing" mapstructure:"editing"` // 编辑设
Paths PathsConfig `json:"paths" yaml:"paths" mapstructure:"paths"` // 路径配 Appearance AppearanceConfig `json:"appearance" yaml:"appearance" mapstructure:"appearance"` // 外观设
KeyBindings KeyBindingsConfig `json:"keyBindings" yaml:"key_bindings" mapstructure:"key_bindings"` // 快捷键设置
Updates UpdatesConfig `json:"updates" yaml:"updates" mapstructure:"updates"` // 更新设置
Metadata ConfigMetadata `json:"metadata" yaml:"metadata" mapstructure:"metadata"` // 配置元数据 Metadata ConfigMetadata `json:"metadata" yaml:"metadata" mapstructure:"metadata"` // 配置元数据
} }
@@ -80,24 +94,33 @@ func NewDefaultAppConfig() *AppConfig {
dataDir := filepath.Join(currentDir, "data") dataDir := filepath.Join(currentDir, "data")
return &AppConfig{ return &AppConfig{
Editor: EditorConfig{ General: GeneralConfig{
AlwaysOnTop: false,
DataPath: dataDir,
},
Editing: EditingConfig{
// 字体设置
FontSize: 13, FontSize: 13,
FontFamily: `"HarmonyOS Sans SC", "HarmonyOS Sans", "Microsoft YaHei", "PingFang SC", "Helvetica Neue", Arial, sans-serif`, FontFamily: `"HarmonyOS Sans SC", "HarmonyOS Sans", "Microsoft YaHei", "PingFang SC", "Helvetica Neue", Arial, sans-serif`,
FontWeight: "normal", FontWeight: "normal",
LineHeight: 1.5, LineHeight: 1.5,
// Tab设置
EnableTabIndent: true, EnableTabIndent: true,
TabSize: 4, TabSize: 4,
TabType: TabTypeSpaces, TabType: TabTypeSpaces,
Language: LangZhCN, // 保存选项
AlwaysOnTop: false,
},
Document: DocumentConfig{
AutoSaveDelay: 5000, // 5秒后自动保存 AutoSaveDelay: 5000, // 5秒后自动保存
ChangeThreshold: 500, // 500个字符变更触发保存 ChangeThreshold: 500, // 500个字符变更触发保存
MinSaveInterval: 1000, // 最小间隔1000毫秒 MinSaveInterval: 1000, // 最小间隔1000毫秒
}, },
Paths: PathsConfig{ Appearance: AppearanceConfig{
DataPath: dataDir, Language: LangZhCN,
},
KeyBindings: KeyBindingsConfig{
// 预留给未来的快捷键配置
},
Updates: UpdatesConfig{
// 预留给未来的更新配置
}, },
Metadata: ConfigMetadata{ Metadata: ConfigMetadata{
Version: "1.0.0", Version: "1.0.0",

View File

@@ -68,7 +68,7 @@ func (cs *ConfigService) validateAndFixValue(key string, value interface{}) (int
fixed := false fixed := false
switch key { switch key {
case "editor.font_size": case "editing.font_size":
if intVal, ok := value.(int); ok { if intVal, ok := value.(int); ok {
if intVal < limits.FontSizeMin { if intVal < limits.FontSizeMin {
cs.logger.Warning("Config: Font size too small, fixing", "original", intVal, "fixed", limits.FontSizeMin) cs.logger.Warning("Config: Font size too small, fixing", "original", intVal, "fixed", limits.FontSizeMin)
@@ -80,7 +80,7 @@ func (cs *ConfigService) validateAndFixValue(key string, value interface{}) (int
} }
} }
case "editor.tab_size": case "editing.tab_size":
if intVal, ok := value.(int); ok { if intVal, ok := value.(int); ok {
if intVal < limits.TabSizeMin { if intVal < limits.TabSizeMin {
cs.logger.Warning("Config: Tab size too small, fixing", "original", intVal, "fixed", limits.TabSizeMin) cs.logger.Warning("Config: Tab size too small, fixing", "original", intVal, "fixed", limits.TabSizeMin)
@@ -92,7 +92,7 @@ func (cs *ConfigService) validateAndFixValue(key string, value interface{}) (int
} }
} }
case "editor.tab_type": case "editing.tab_type":
if strVal, ok := value.(string); ok { if strVal, ok := value.(string); ok {
validTypes := []string{string(models.TabTypeSpaces), string(models.TabTypeTab)} validTypes := []string{string(models.TabTypeSpaces), string(models.TabTypeTab)}
isValid := false isValid := false
@@ -108,7 +108,7 @@ func (cs *ConfigService) validateAndFixValue(key string, value interface{}) (int
} }
} }
case "editor.language": case "appearance.language":
if strVal, ok := value.(string); ok { if strVal, ok := value.(string); ok {
validLanguages := []string{string(models.LangZhCN), string(models.LangEnUS)} validLanguages := []string{string(models.LangZhCN), string(models.LangEnUS)}
isValid := false isValid := false
@@ -124,7 +124,7 @@ func (cs *ConfigService) validateAndFixValue(key string, value interface{}) (int
} }
} }
case "document.auto_save_delay": case "editing.auto_save_delay":
if intVal, ok := value.(int); ok { if intVal, ok := value.(int); ok {
if intVal < 1000 { if intVal < 1000 {
cs.logger.Warning("Config: Auto save delay too small, fixing", "original", intVal, "fixed", 1000) cs.logger.Warning("Config: Auto save delay too small, fixing", "original", intVal, "fixed", 1000)
@@ -136,7 +136,7 @@ func (cs *ConfigService) validateAndFixValue(key string, value interface{}) (int
} }
} }
case "document.change_threshold": case "editing.change_threshold":
if intVal, ok := value.(int); ok { if intVal, ok := value.(int); ok {
if intVal < 10 { if intVal < 10 {
cs.logger.Warning("Config: Change threshold too small, fixing", "original", intVal, "fixed", 10) cs.logger.Warning("Config: Change threshold too small, fixing", "original", intVal, "fixed", 10)
@@ -148,7 +148,7 @@ func (cs *ConfigService) validateAndFixValue(key string, value interface{}) (int
} }
} }
case "document.min_save_interval": case "editing.min_save_interval":
if intVal, ok := value.(int); ok { if intVal, ok := value.(int); ok {
if intVal < 100 { if intVal < 100 {
cs.logger.Warning("Config: Min save interval too small, fixing", "original", intVal, "fixed", 100) cs.logger.Warning("Config: Min save interval too small, fixing", "original", intVal, "fixed", 100)
@@ -175,39 +175,39 @@ func (cs *ConfigService) validateAllConfig() error {
} }
// 验证编辑器配置 // 验证编辑器配置
if fixedValue, fixed := cs.validateAndFixValue("editor.font_size", config.Editor.FontSize); fixed { if fixedValue, fixed := cs.validateAndFixValue("editing.font_size", config.Editing.FontSize); fixed {
cs.viper.Set("editor.font_size", fixedValue) cs.viper.Set("editing.font_size", fixedValue)
hasChanges = true hasChanges = true
} }
if fixedValue, fixed := cs.validateAndFixValue("editor.tab_size", config.Editor.TabSize); fixed { if fixedValue, fixed := cs.validateAndFixValue("editing.tab_size", config.Editing.TabSize); fixed {
cs.viper.Set("editor.tab_size", fixedValue) cs.viper.Set("editing.tab_size", fixedValue)
hasChanges = true hasChanges = true
} }
if fixedValue, fixed := cs.validateAndFixValue("editor.tab_type", string(config.Editor.TabType)); fixed { if fixedValue, fixed := cs.validateAndFixValue("editing.tab_type", string(config.Editing.TabType)); fixed {
cs.viper.Set("editor.tab_type", fixedValue) cs.viper.Set("editing.tab_type", fixedValue)
hasChanges = true hasChanges = true
} }
if fixedValue, fixed := cs.validateAndFixValue("editor.language", string(config.Editor.Language)); fixed { if fixedValue, fixed := cs.validateAndFixValue("appearance.language", string(config.Appearance.Language)); fixed {
cs.viper.Set("editor.language", fixedValue) cs.viper.Set("appearance.language", fixedValue)
hasChanges = true hasChanges = true
} }
// 验证文档配置 // 验证保存选项配置
if fixedValue, fixed := cs.validateAndFixValue("document.auto_save_delay", config.Document.AutoSaveDelay); fixed { if fixedValue, fixed := cs.validateAndFixValue("editing.auto_save_delay", config.Editing.AutoSaveDelay); fixed {
cs.viper.Set("document.auto_save_delay", fixedValue) cs.viper.Set("editing.auto_save_delay", fixedValue)
hasChanges = true hasChanges = true
} }
if fixedValue, fixed := cs.validateAndFixValue("document.change_threshold", config.Document.ChangeThreshold); fixed { if fixedValue, fixed := cs.validateAndFixValue("editing.change_threshold", config.Editing.ChangeThreshold); fixed {
cs.viper.Set("document.change_threshold", fixedValue) cs.viper.Set("editing.change_threshold", fixedValue)
hasChanges = true hasChanges = true
} }
if fixedValue, fixed := cs.validateAndFixValue("document.min_save_interval", config.Document.MinSaveInterval); fixed { if fixedValue, fixed := cs.validateAndFixValue("editing.min_save_interval", config.Editing.MinSaveInterval); fixed {
cs.viper.Set("document.min_save_interval", fixedValue) cs.viper.Set("editing.min_save_interval", fixedValue)
hasChanges = true hasChanges = true
} }
@@ -280,24 +280,24 @@ func NewConfigService(logger *log.LoggerService) *ConfigService {
func setDefaults(v *viper.Viper) { func setDefaults(v *viper.Viper) {
defaultConfig := models.NewDefaultAppConfig() defaultConfig := models.NewDefaultAppConfig()
// 编辑器配置默认值 // 通用设置默认值
v.SetDefault("editor.font_size", defaultConfig.Editor.FontSize) v.SetDefault("general.always_on_top", defaultConfig.General.AlwaysOnTop)
v.SetDefault("editor.font_family", defaultConfig.Editor.FontFamily) v.SetDefault("general.data_path", defaultConfig.General.DataPath)
v.SetDefault("editor.font_weight", defaultConfig.Editor.FontWeight)
v.SetDefault("editor.line_height", defaultConfig.Editor.LineHeight)
v.SetDefault("editor.enable_tab_indent", defaultConfig.Editor.EnableTabIndent)
v.SetDefault("editor.tab_size", defaultConfig.Editor.TabSize)
v.SetDefault("editor.tab_type", defaultConfig.Editor.TabType)
v.SetDefault("editor.language", defaultConfig.Editor.Language)
v.SetDefault("editor.always_on_top", defaultConfig.Editor.AlwaysOnTop)
// 文档配置默认值 // 编辑设置默认值
v.SetDefault("document.auto_save_delay", defaultConfig.Document.AutoSaveDelay) v.SetDefault("editing.font_size", defaultConfig.Editing.FontSize)
v.SetDefault("document.change_threshold", defaultConfig.Document.ChangeThreshold) v.SetDefault("editing.font_family", defaultConfig.Editing.FontFamily)
v.SetDefault("document.min_save_interval", defaultConfig.Document.MinSaveInterval) v.SetDefault("editing.font_weight", defaultConfig.Editing.FontWeight)
v.SetDefault("editing.line_height", defaultConfig.Editing.LineHeight)
v.SetDefault("editing.enable_tab_indent", defaultConfig.Editing.EnableTabIndent)
v.SetDefault("editing.tab_size", defaultConfig.Editing.TabSize)
v.SetDefault("editing.tab_type", defaultConfig.Editing.TabType)
v.SetDefault("editing.auto_save_delay", defaultConfig.Editing.AutoSaveDelay)
v.SetDefault("editing.change_threshold", defaultConfig.Editing.ChangeThreshold)
v.SetDefault("editing.min_save_interval", defaultConfig.Editing.MinSaveInterval)
// 路径配置默认值 // 外观设置默认值
v.SetDefault("paths.data_path", defaultConfig.Paths.DataPath) v.SetDefault("appearance.language", defaultConfig.Appearance.Language)
// 元数据默认值 // 元数据默认值
v.SetDefault("metadata.version", defaultConfig.Metadata.Version) v.SetDefault("metadata.version", defaultConfig.Metadata.Version)

View File

@@ -147,9 +147,9 @@ func (ds *DocumentService) scheduleAutoSave() {
// 打印保存设置,便于调试 // 打印保存设置,便于调试
ds.logger.Debug("Document: Auto save settings", ds.logger.Debug("Document: Auto save settings",
"autoSaveDelay", config.Document.AutoSaveDelay, "autoSaveDelay", config.Editing.AutoSaveDelay,
"changeThreshold", config.Document.ChangeThreshold, "changeThreshold", config.Editing.ChangeThreshold,
"minSaveInterval", config.Document.MinSaveInterval) "minSaveInterval", config.Editing.MinSaveInterval)
ds.lock.Lock() ds.lock.Lock()
defer ds.lock.Unlock() defer ds.lock.Unlock()
@@ -160,7 +160,7 @@ func (ds *DocumentService) scheduleAutoSave() {
} }
// 创建新的自动保存定时器 // 创建新的自动保存定时器
autoSaveDelay := config.Document.AutoSaveDelay autoSaveDelay := config.Editing.AutoSaveDelay
ds.logger.Debug("Document: Scheduling auto save", "delay", autoSaveDelay) ds.logger.Debug("Document: Scheduling auto save", "delay", autoSaveDelay)
ds.scheduleTimerWithDelay(autoSaveDelay) ds.scheduleTimerWithDelay(autoSaveDelay)
} }
@@ -197,7 +197,7 @@ func (ds *DocumentService) saveToStore(trigger SaveTrigger) {
// 如果成功获取了配置,使用配置值 // 如果成功获取了配置,使用配置值
if err == nil && config != nil { if err == nil && config != nil {
minInterval = config.Document.MinSaveInterval minInterval = config.Editing.MinSaveInterval
} }
// 如果是自动保存,检查最小保存间隔 // 如果是自动保存,检查最小保存间隔
@@ -305,7 +305,7 @@ func (ds *DocumentService) ensureDocumentsDir() error {
} }
// 创建文档目录 // 创建文档目录
docsDir := filepath.Join(config.Paths.DataPath, "docs") docsDir := filepath.Join(config.General.DataPath, "docs")
err = os.MkdirAll(docsDir, 0755) err = os.MkdirAll(docsDir, 0755)
if err != nil { if err != nil {
return err return err
@@ -320,7 +320,7 @@ func (ds *DocumentService) getDocumentsDir() (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
return filepath.Join(config.Paths.DataPath, "docs"), nil return filepath.Join(config.General.DataPath, "docs"), nil
} }
// getDefaultDocumentPath 获取默认文档路径 // getDefaultDocumentPath 获取默认文档路径
@@ -405,7 +405,7 @@ func (ds *DocumentService) UpdateActiveDocumentContent(content string) error {
// 如果成功获取了配置,使用配置值 // 如果成功获取了配置,使用配置值
if err == nil && config != nil { if err == nil && config != nil {
threshold = config.Document.ChangeThreshold threshold = config.Editing.ChangeThreshold
} }
ds.lock.Lock() ds.lock.Lock()
@@ -520,26 +520,26 @@ func (ds *DocumentService) GetDiffInfo(oldText, newText string) DiffResult {
} }
// GetSaveSettings 获取文档保存设置 // GetSaveSettings 获取文档保存设置
func (ds *DocumentService) GetSaveSettings() (*models.DocumentConfig, error) { func (ds *DocumentService) GetSaveSettings() (*models.EditingConfig, error) {
config, err := ds.configService.GetConfig() config, err := ds.configService.GetConfig()
if err != nil { if err != nil {
return nil, &DocumentError{Operation: "get_save_settings", Err: err} return nil, &DocumentError{Operation: "get_save_settings", Err: err}
} }
return &config.Document, nil return &config.Editing, nil
} }
// UpdateSaveSettings 更新文档保存设置 // UpdateSaveSettings 更新文档保存设置
func (ds *DocumentService) UpdateSaveSettings(docConfig models.DocumentConfig) error { func (ds *DocumentService) UpdateSaveSettings(docConfig models.EditingConfig) error {
// 使用配置服务的 Set 方法更新文档配置 // 使用配置服务的 Set 方法更新文档配置
if err := ds.configService.Set("document.auto_save_delay", docConfig.AutoSaveDelay); err != nil { if err := ds.configService.Set("editing.auto_save_delay", docConfig.AutoSaveDelay); err != nil {
return &DocumentError{Operation: "update_save_settings_auto_save_delay", Err: err} return &DocumentError{Operation: "update_save_settings_auto_save_delay", Err: err}
} }
if err := ds.configService.Set("document.change_threshold", docConfig.ChangeThreshold); err != nil { if err := ds.configService.Set("editing.change_threshold", docConfig.ChangeThreshold); err != nil {
return &DocumentError{Operation: "update_save_settings_change_threshold", Err: err} return &DocumentError{Operation: "update_save_settings_change_threshold", Err: err}
} }
if err := ds.configService.Set("document.min_save_interval", docConfig.MinSaveInterval); err != nil { if err := ds.configService.Set("editing.min_save_interval", docConfig.MinSaveInterval); err != nil {
return &DocumentError{Operation: "update_save_settings_min_save_interval", Err: err} return &DocumentError{Operation: "update_save_settings_min_save_interval", Err: err}
} }