Skip to content

Commit 28cb0b4

Browse files
committed
feat (core): 增加编辑器配置
1 parent 42aa116 commit 28cb0b4

6 files changed

Lines changed: 595 additions & 53 deletions

File tree

src-tauri/src/config.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,29 @@ use crate::plugin::PluginManagerState;
33
use crate::plugins::PluginConfig;
44
use log::{info, warn};
55
use serde::{Deserialize, Serialize};
6+
use serde_json::Value::Bool;
67
use std::fs;
78
use std::path::PathBuf;
89
use std::sync::Mutex;
910
use tauri::{AppHandle, Manager, command};
1011

1112
static CONFIG_MANAGER: Mutex<Option<ConfigManager>> = Mutex::new(None);
1213

14+
#[derive(Debug, Clone, Serialize, Deserialize)]
15+
pub struct EditorConfig {
16+
pub indent_with_tab: Option<bool>, // 是否使用 tab 缩进
17+
pub tab_size: Option<u32>, // tab 缩进, 空格数,默认为 2
18+
pub theme: Option<String>, // 编辑器主题
19+
}
20+
1321
#[derive(Debug, Clone, Serialize, Deserialize)]
1422
pub struct AppConfig {
1523
pub log_directory: Option<String>,
1624
pub auto_clear_logs: Option<bool>,
1725
pub keep_log_days: Option<u32>,
1826
pub theme: Option<String>,
1927
pub plugins: Option<Vec<PluginConfig>>,
28+
pub editor: Option<EditorConfig>,
2029
}
2130

2231
impl Default for AppConfig {
@@ -27,6 +36,11 @@ impl Default for AppConfig {
2736
keep_log_days: Some(30),
2837
theme: Some("system".to_string()),
2938
plugins: Some(vec![]),
39+
editor: Some(EditorConfig {
40+
indent_with_tab: Some(true),
41+
tab_size: Some(2),
42+
theme: Some("githubLight".to_string()),
43+
}),
3044
}
3145
}
3246
}
@@ -75,6 +89,16 @@ impl ConfigManager {
7589
// 合并插件配置(现有配置 + 默认配置中缺失的插件)
7690
config.plugins = Self::merge_plugins_config(config.plugins, app_handle);
7791

92+
// 检查并设置 editor 默认配置
93+
if config.editor.is_none() {
94+
config.editor = Some(EditorConfig {
95+
indent_with_tab: Some(true),
96+
tab_size: Some(2),
97+
theme: Some("githubLight".to_string()),
98+
});
99+
println!("读取配置 -> 添加默认 editor 配置");
100+
}
101+
78102
Ok(config)
79103
}
80104
Err(e) => {
@@ -170,6 +194,11 @@ impl ConfigManager {
170194
keep_log_days: Some(30),
171195
theme: Some("system".to_string()),
172196
plugins: Self::get_default_plugins_config(app_handle),
197+
editor: Some(EditorConfig {
198+
indent_with_tab: Some(true),
199+
tab_size: Some(2),
200+
theme: Some("githubLight".to_string()),
201+
}),
173202
}
174203
}
175204

src/components/CodeEditor.vue

Lines changed: 12 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,16 @@
44
style="width: 100%; height: 100%"
55
:model-value="modelValue"
66
:extensions="extensions"
7+
:indent-with-tab="editorConfig?.indent_with_tab"
8+
:tab-size="editorConfig?.tab_size"
79
@change="handleInput"/>
810
</div>
911
</template>
1012

1113
<script setup lang="ts">
12-
import { nextTick, onMounted, ref, watch } from 'vue'
14+
import { onMounted } from 'vue'
1315
import { Codemirror } from 'vue-codemirror'
14-
import { python } from '@codemirror/lang-python'
15-
import { javascript } from '@codemirror/lang-javascript'
16-
import { go } from '@codemirror/lang-go'
17-
import { githubLight } from '@uiw/codemirror-themes-all'
16+
import { useCodeMirrorEditor } from '../composables/useCodeMirrorEditor'
1817
1918
const props = defineProps<{
2019
modelValue: string
@@ -25,57 +24,18 @@ const emit = defineEmits<{
2524
'update:modelValue': [value: string]
2625
}>()
2726
27+
const {
28+
isReady,
29+
extensions,
30+
editorConfig,
31+
initializeEditor
32+
} = useCodeMirrorEditor(props, emit)
33+
2834
const handleInput = (value: string) => {
2935
emit('update:modelValue', value)
3036
}
3137
32-
const isReady = ref(false)
33-
const extensions = ref<[]>([])
34-
35-
// 获取语言扩展
36-
const getLanguageExtension = (language: string): any | null => {
37-
switch (language) {
38-
case 'python2':
39-
case 'python3':
40-
return python()
41-
case 'nodejs':
42-
return javascript()
43-
case 'go':
44-
return go()
45-
default:
46-
return null
47-
}
48-
}
49-
50-
// 更新扩展的函数
51-
const updateExtensions = async () => {
52-
const result = [githubLight]
53-
54-
if (props.language) {
55-
const langExtension = getLanguageExtension(props.language)
56-
if (langExtension) {
57-
result.push(langExtension)
58-
}
59-
}
60-
61-
extensions.value = result as any
62-
63-
// 如果组件还没准备好,等待下一个 tick 后设置为准备好
64-
if (!isReady.value) {
65-
await nextTick()
66-
isReady.value = true
67-
}
68-
}
69-
70-
// 监听语言变化
71-
watch(() => props.language, async () => {
72-
isReady.value = false
73-
await nextTick()
74-
await updateExtensions()
75-
}, { immediate: false })
76-
77-
// 组件挂载时初始化
7838
onMounted(async () => {
79-
await updateExtensions()
39+
await initializeEditor()
8040
})
8141
</script>

src/components/Settings.vue

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
<General/>
1212
</template>
1313

14+
<!-- 编辑器配置 -->
15+
<template #editor>
16+
<Editor v-if="activeTab === 'editor'"/>
17+
</template>
18+
1419
<!-- 语言配置 -->
1520
<template #language>
1621
<Language v-if="activeTab === 'language'"/>
@@ -21,16 +26,18 @@
2126

2227
<script setup lang="ts">
2328
import { nextTick, onMounted, ref } from 'vue'
24-
import { BracesIcon, ShieldIcon } from 'lucide-vue-next'
29+
import { BracesIcon, CodeIcon, ShieldIcon } from 'lucide-vue-next'
2530
import Modal from '../ui/Modal.vue'
2631
import Tabs from '../ui/Tabs.vue'
2732
import General from './setting/General.vue'
2833
import Language from './setting/Language.vue'
34+
import Editor from './setting/Editor.vue'
2935
3036
const isVisible = ref(false)
3137
const activeTab = ref('general')
3238
const tabsData = [
3339
{ key: 'general', label: '通用', icon: ShieldIcon },
40+
{ key: 'editor', label: '编辑器', icon: CodeIcon },
3441
{ key: 'language', label: '语言', icon: BracesIcon }
3542
]
3643

src/components/setting/Editor.vue

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<template>
2+
<div v-if="editorConfig" class="space-y-2">
3+
<div>
4+
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
5+
是否使用 tab 缩进
6+
</label>
7+
<div class="flex gap-2">
8+
<input v-model="editorConfig.indent_with_tab"
9+
type="checkbox"
10+
placeholder="超时时间(秒),默认 30 秒"
11+
class="flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-transparent text-sm"/>
12+
</div>
13+
</div>
14+
15+
<div>
16+
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
17+
缩进空格数
18+
</label>
19+
<div class="flex gap-2">
20+
<input v-model="editorConfig.tab_size"
21+
type="number"
22+
:disabled="!editorConfig.indent_with_tab"
23+
placeholder="缩进空格数,默认 2 秒"
24+
class="flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-transparent text-sm"
25+
:class="[!editorConfig.indent_with_tab ? 'opacity-50 cursor-not-allowed' : '']"/>
26+
</div>
27+
</div>
28+
29+
<div>
30+
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
31+
编辑器主题
32+
</label>
33+
<div class="flex gap-2">
34+
<Select v-model="editorConfig.theme"
35+
class="w-1/4"
36+
placeholder="选择编辑器主题"
37+
:options="themeOptions"/>
38+
</div>
39+
</div>
40+
</div>
41+
</template>
42+
43+
<script setup lang="ts">
44+
import { onMounted } from 'vue'
45+
import Select from '../../ui/Select.vue'
46+
import { useEditorConfig } from '../../composables/useEditorConfig'
47+
48+
const emit = defineEmits<{
49+
'settings-changed': [config: any]
50+
'error': [message: string]
51+
}>()
52+
53+
const {
54+
editorConfig,
55+
themeOptions,
56+
loadConfig
57+
} = useEditorConfig(emit)
58+
59+
onMounted(async () => {
60+
await loadConfig()
61+
})
62+
</script>

0 commit comments

Comments
 (0)