feat: 添加设置文件编辑器字体大小的功能
This commit is contained in:
@@ -5,9 +5,11 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
|
||||
import * as monaco from 'monaco-editor';
|
||||
import { useAppearanceStore } from '../stores/appearance.store'; // <-- 导入 Store
|
||||
import { storeToRefs } from 'pinia'; // <-- 导入 storeToRefs
|
||||
|
||||
// Props for the component (will be expanded later)
|
||||
const fontSize = ref(14); // 添加字体大小状态,默认 14
|
||||
// const fontSize = ref(14); // <-- 移除本地 fontSize ref
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: { // Use modelValue for v-model support
|
||||
@@ -34,13 +36,37 @@ const emit = defineEmits(['update:modelValue', 'request-save']);
|
||||
const editorContainer = ref<HTMLElement | null>(null);
|
||||
let editorInstance: monaco.editor.IStandaloneCodeEditor | null = null;
|
||||
|
||||
// --- Appearance Store ---
|
||||
const appearanceStore = useAppearanceStore();
|
||||
const { currentEditorFontSize } = storeToRefs(appearanceStore); // <-- 获取编辑器字体大小
|
||||
|
||||
// --- Debounce function ---
|
||||
let debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
const debounce = (func: Function, delay: number) => {
|
||||
return (...args: any[]) => {
|
||||
if (debounceTimer) {
|
||||
clearTimeout(debounceTimer);
|
||||
}
|
||||
debounceTimer = setTimeout(() => {
|
||||
func(...args);
|
||||
debounceTimer = null;
|
||||
}, delay);
|
||||
};
|
||||
};
|
||||
|
||||
// Debounced function to save font size setting
|
||||
const debouncedSetEditorFontSize = debounce((size: number) => {
|
||||
console.log(`[MonacoEditor] Debounced save triggered. Saving font size: ${size}`);
|
||||
appearanceStore.setEditorFontSize(size);
|
||||
}, 500); // 500ms delay
|
||||
|
||||
onMounted(() => {
|
||||
if (editorContainer.value) {
|
||||
editorInstance = monaco.editor.create(editorContainer.value, {
|
||||
value: props.modelValue,
|
||||
language: props.language,
|
||||
theme: props.theme,
|
||||
fontSize: fontSize.value, // 使用 ref 作为初始字体大小
|
||||
fontSize: currentEditorFontSize.value, // <-- 使用 Store 的字体大小
|
||||
automaticLayout: true, // Auto resize editor on container resize
|
||||
readOnly: props.readOnly,
|
||||
// Add more options as needed
|
||||
@@ -103,41 +129,51 @@ onMounted(() => {
|
||||
},
|
||||
});
|
||||
|
||||
// 添加鼠标滚轮缩放功能
|
||||
const editorDomNode = editorInstance?.getDomNode(); // 获取编辑器 DOM 节点
|
||||
if (editorDomNode) { // 确认编辑器 DOM 节点存在
|
||||
console.log('[MonacoEditor] Adding wheel event listener to editor DOM node.'); // 调试日志
|
||||
editorDomNode.addEventListener('wheel', (event: WheelEvent) => {
|
||||
console.log('[MonacoEditor] Wheel event detected on editor DOM node.'); // 调试日志
|
||||
// 只在按下Ctrl键时才触发缩放
|
||||
if (event.ctrlKey) {
|
||||
console.log('[MonacoEditor] Ctrl key pressed during wheel event.'); // 调试日志
|
||||
event.preventDefault(); // 阻止默认的滚动行为
|
||||
// --- 添加带防抖的鼠标滚轮缩放功能 ---
|
||||
const editorDomNode = editorInstance?.getDomNode();
|
||||
if (editorDomNode) {
|
||||
console.log('[MonacoEditor] Adding wheel event listener with debounce.');
|
||||
editorDomNode.addEventListener('wheel', (event: WheelEvent) => {
|
||||
if (event.ctrlKey) {
|
||||
event.preventDefault();
|
||||
|
||||
// 根据滚轮方向调整字体大小
|
||||
if (event.deltaY < 0) {
|
||||
// 向上滚动,增大字体
|
||||
fontSize.value = Math.min(fontSize.value + 1, 40); // 设置最大字体大小为40
|
||||
} else {
|
||||
// 向下滚动,减小字体
|
||||
fontSize.value = Math.max(fontSize.value - 1, 8); // 设置最小字体大小为8
|
||||
}
|
||||
// Calculate new font size immediately
|
||||
const currentSize = editorInstance?.getOption(monaco.editor.EditorOption.fontSize) ?? currentEditorFontSize.value;
|
||||
let newSize: number;
|
||||
if (event.deltaY < 0) {
|
||||
newSize = Math.min(currentSize + 1, 40); // Increase size, max 40
|
||||
} else {
|
||||
newSize = Math.max(currentSize - 1, 8); // Decrease size, min 8
|
||||
}
|
||||
|
||||
// 更新编辑器字体大小
|
||||
if (editorInstance) {
|
||||
console.log(`[MonacoEditor] Attempting to update font size to: ${fontSize.value}`); // 调试日志
|
||||
editorInstance.updateOptions({ fontSize: fontSize.value });
|
||||
console.log(`[MonacoEditor] Font size changed to: ${fontSize.value}`); // 添加日志
|
||||
} else {
|
||||
console.warn('[MonacoEditor] editorInstance is null, cannot update font size.'); // 调试日志
|
||||
}
|
||||
} else {
|
||||
// console.log('[MonacoEditor] Ctrl key NOT pressed during wheel event.'); // 可选调试日志
|
||||
}
|
||||
}, { passive: false }); // 设置 passive: false 允许 preventDefault
|
||||
// Update visual font size immediately
|
||||
if (editorInstance && newSize !== currentSize) {
|
||||
console.log(`[MonacoEditor] Immediate visual update to font size: ${newSize}`);
|
||||
editorInstance.updateOptions({ fontSize: newSize });
|
||||
|
||||
// Trigger debounced save
|
||||
debouncedSetEditorFontSize(newSize);
|
||||
}
|
||||
}
|
||||
}, { passive: false }); // passive: false allows preventDefault
|
||||
} else {
|
||||
console.error('[MonacoEditor] editorDomNode is null, cannot add wheel listener.'); // 调试日志
|
||||
console.error('[MonacoEditor] editorDomNode is null, cannot add wheel listener.');
|
||||
}
|
||||
// --- End of wheel event listener ---
|
||||
|
||||
// --- 移除鼠标滚轮缩放功能 ---
|
||||
// const editorDomNode = editorInstance?.getDomNode();
|
||||
// if (editorDomNode) {
|
||||
// editorDomNode.addEventListener('wheel', (event: WheelEvent) => {
|
||||
// if (event.ctrlKey) {
|
||||
// event.preventDefault();
|
||||
// // ... (移除字体大小调整逻辑) ...
|
||||
// // if (editorInstance) {
|
||||
// // editorInstance.updateOptions({ fontSize: fontSize.value }); // 使用本地 fontSize
|
||||
// // }
|
||||
// }
|
||||
// }, { passive: false });
|
||||
// }
|
||||
|
||||
}
|
||||
});
|
||||
@@ -171,6 +207,14 @@ watch(() => props.readOnly, (newReadOnly) => {
|
||||
});
|
||||
|
||||
|
||||
// Watch for changes in the global editor font size setting
|
||||
watch(currentEditorFontSize, (newSize) => {
|
||||
if (editorInstance) {
|
||||
console.log(`[MonacoEditor] Global font size changed to: ${newSize}. Updating editor.`);
|
||||
editorInstance.updateOptions({ fontSize: newSize });
|
||||
}
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (editorInstance) {
|
||||
editorInstance.dispose();
|
||||
|
||||
@@ -15,7 +15,8 @@ const {
|
||||
activeTerminalThemeId,
|
||||
availableTerminalThemes,
|
||||
currentTerminalFontFamily,
|
||||
currentTerminalFontSize, // <-- 添加
|
||||
currentTerminalFontSize,
|
||||
currentEditorFontSize, // <-- 新增
|
||||
pageBackgroundImage,
|
||||
// pageBackgroundOpacity, // Removed
|
||||
terminalBackgroundImage,
|
||||
@@ -25,7 +26,8 @@ const {
|
||||
// --- 本地状态用于编辑 ---
|
||||
const editableUiTheme = ref<Record<string, string>>({});
|
||||
const editableTerminalFontFamily = ref('');
|
||||
const editableTerminalFontSize = ref(14); // <-- 添加,默认值 14
|
||||
const editableTerminalFontSize = ref(14);
|
||||
const editableEditorFontSize = ref(14); // <-- 新增,编辑器字体大小
|
||||
// const editablePageBackgroundOpacity = ref(1.0); // Removed
|
||||
// const editableTerminalBackgroundOpacity = ref(1.0); // Removed
|
||||
|
||||
@@ -52,7 +54,8 @@ const initializeEditableState = () => {
|
||||
// 深拷贝 UI 主题
|
||||
editableUiTheme.value = JSON.parse(JSON.stringify(currentUiTheme.value || {}));
|
||||
editableTerminalFontFamily.value = currentTerminalFontFamily.value;
|
||||
editableTerminalFontSize.value = currentTerminalFontSize.value; // <-- 添加
|
||||
editableTerminalFontSize.value = currentTerminalFontSize.value;
|
||||
editableEditorFontSize.value = currentEditorFontSize.value; // <-- 新增
|
||||
selectedTerminalThemeId.value = activeTerminalThemeId.value ?? null; // 初始化下拉框
|
||||
// editablePageBackgroundOpacity.value = pageBackgroundOpacity.value; // Removed
|
||||
// editableTerminalBackgroundOpacity.value = terminalBackgroundOpacity.value; // Removed
|
||||
@@ -67,20 +70,22 @@ onMounted(initializeEditableState);
|
||||
// 监听 store 变化以更新本地状态 (例如重置或外部更改)
|
||||
// 只监听不需要编辑的状态或用于初始化的状态
|
||||
watch([
|
||||
currentUiTheme, currentTerminalFontFamily, currentTerminalFontSize, activeTerminalThemeId // <-- 添加 currentTerminalFontSize
|
||||
currentUiTheme, currentTerminalFontFamily, currentTerminalFontSize, currentEditorFontSize, activeTerminalThemeId // <-- 添加 currentEditorFontSize
|
||||
// pageBackgroundOpacity, terminalBackgroundOpacity // Removed dependencies
|
||||
], (newVals, oldVals) => {
|
||||
// 仅当非编辑状态时,或活动主题ID变化时,才同步下拉框和非编辑状态
|
||||
// 注意:索引现在需要调整,因为 newVals 数组长度变了
|
||||
if (!isEditingTheme.value || newVals[3] !== oldVals[3]) { // <-- 索引从 2 改为 3
|
||||
// 注意:索引现在需要调整
|
||||
const activeThemeIdIndex = 4; // activeTerminalThemeId 的新索引
|
||||
if (!isEditingTheme.value || newVals[activeThemeIdIndex] !== oldVals[activeThemeIdIndex]) {
|
||||
initializeEditableState();
|
||||
} else {
|
||||
// 如果正在编辑,只更新非编辑相关的部分
|
||||
editableUiTheme.value = JSON.parse(JSON.stringify(newVals[0] || {}));
|
||||
editableTerminalFontFamily.value = newVals[1];
|
||||
editableTerminalFontSize.value = newVals[2]; // <-- 添加
|
||||
// editablePageBackgroundOpacity.value = newVals[4]; // Removed
|
||||
// editableTerminalBackgroundOpacity.value = newVals[5]; // Removed
|
||||
editableTerminalFontSize.value = newVals[2];
|
||||
editableEditorFontSize.value = newVals[3]; // <-- 新增同步
|
||||
// editablePageBackgroundOpacity.value = newVals[5]; // Removed
|
||||
// editableTerminalBackgroundOpacity.value = newVals[6]; // Removed
|
||||
}
|
||||
}, { deep: true });
|
||||
|
||||
@@ -101,7 +106,7 @@ const closeCustomizer = () => {
|
||||
};
|
||||
|
||||
// 当前活动的标签页
|
||||
const currentTab = ref<'ui' | 'terminal' | 'background'>('ui');
|
||||
const currentTab = ref<'ui' | 'terminal' | 'background' | 'other'>('ui'); // <-- 添加 'other'
|
||||
|
||||
// --- 处理函数 ---
|
||||
|
||||
@@ -157,6 +162,22 @@ const handleSaveTerminalFontSize = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 保存编辑器字体大小
|
||||
const handleSaveEditorFontSize = async () => {
|
||||
try {
|
||||
const size = Number(editableEditorFontSize.value);
|
||||
if (isNaN(size) || size <= 0) {
|
||||
alert(t('styleCustomizer.errorInvalidEditorFontSize')); // 需要添加翻译
|
||||
return;
|
||||
}
|
||||
await appearanceStore.setEditorFontSize(size);
|
||||
alert(t('styleCustomizer.editorFontSizeSaved')); // 需要添加翻译
|
||||
} catch (error: any) {
|
||||
console.error("保存编辑器字体大小失败:", error);
|
||||
alert(t('styleCustomizer.editorFontSizeSaveFailed', { message: error.message })); // 需要添加翻译
|
||||
}
|
||||
};
|
||||
|
||||
// 更改激活的终端主题
|
||||
const handleTerminalThemeChange = async () => {
|
||||
try {
|
||||
@@ -388,6 +409,9 @@ const formatXtermLabel = (key: keyof ITheme): string => {
|
||||
<button @click="currentTab = 'background'" :class="{ active: currentTab === 'background' }" :disabled="isEditingTheme">
|
||||
{{ t('styleCustomizer.backgroundSettings') }}
|
||||
</button>
|
||||
<button @click="currentTab = 'other'" :class="{ active: currentTab === 'other' }" :disabled="isEditingTheme">
|
||||
{{ t('styleCustomizer.otherSettings') }} <!-- 需要添加翻译 -->
|
||||
</button>
|
||||
</nav>
|
||||
<main class="panel-main">
|
||||
<section v-if="currentTab === 'ui'">
|
||||
@@ -529,6 +553,15 @@ const formatXtermLabel = (key: keyof ITheme): string => {
|
||||
<!-- Removed Opacity Slider -->
|
||||
|
||||
</section>
|
||||
<section v-if="currentTab === 'other'">
|
||||
<h3>{{ t('styleCustomizer.otherSettings') }}</h3> <!-- 需要添加翻译 -->
|
||||
<!-- 编辑器字体大小设置 -->
|
||||
<div class="form-group">
|
||||
<label for="editorFontSize">{{ t('styleCustomizer.editorFontSize') }}:</label> <!-- 需要添加翻译 -->
|
||||
<input type="number" id="editorFontSize" v-model.number="editableEditorFontSize" class="number-input" min="1" />
|
||||
<button @click="handleSaveEditorFontSize" class="button-inline">{{ t('common.save') }}</button>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
<footer class="panel-footer">
|
||||
@@ -722,6 +755,7 @@ section[v-if*="isEditingTheme"] .form-group {
|
||||
/* 输入控件 */
|
||||
.form-group input[type="color"],
|
||||
.form-group input[type="text"].text-input,
|
||||
.form-group input[type="number"].number-input, /* <-- 添加 number-input */
|
||||
.form-group select {
|
||||
grid-column: 2 / 3;
|
||||
border: 1px solid var(--border-color);
|
||||
@@ -751,6 +785,7 @@ section[v-if*="isEditingTheme"] .form-group {
|
||||
/* Input controls (text, color, select) */
|
||||
.form-group input[type="color"],
|
||||
.form-group input[type="text"].text-input,
|
||||
.form-group input[type="number"].number-input, /* <-- 添加 number-input */
|
||||
.form-group select {
|
||||
grid-column: 2 / 3; /* Place in the second column */
|
||||
/* Existing styles below... */
|
||||
@@ -772,7 +807,11 @@ section[v-if*="isEditingTheme"] .form-group {
|
||||
justify-self: start;
|
||||
border-radius: 4px; /* 保持圆角一致 */
|
||||
}
|
||||
.form-group input:focus, .form-group select:focus {
|
||||
.form-group input[type="number"].number-input {
|
||||
max-width: 100px; /* 限制数字输入框宽度 */
|
||||
justify-self: start;
|
||||
}
|
||||
.form-group input:focus, .form-group select:focus, .form-group input[type="number"]:focus { /* <-- 添加 number input focus */
|
||||
border-color: var(--link-active-color);
|
||||
outline: 0;
|
||||
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.15); /* 调整聚焦阴影 */
|
||||
|
||||
@@ -77,7 +77,12 @@
|
||||
"terminalFontSize": "Terminal Font Size",
|
||||
"errorInvalidFontSize": "Invalid font size. Please enter a positive number.",
|
||||
"terminalFontSizeSaved": "Terminal font size saved.",
|
||||
"terminalFontSizeSaveFailed": "Failed to save terminal font size: {message}"
|
||||
"terminalFontSizeSaveFailed": "Failed to save terminal font size: {message}",
|
||||
"otherSettings": "Other Settings",
|
||||
"editorFontSize": "Editor Font Size",
|
||||
"editorFontSizeSaved": "Editor font size saved.",
|
||||
"editorFontSizeSaveFailed": "Failed to save editor font size: {message}",
|
||||
"errorInvalidEditorFontSize": "Invalid font size. Please enter a positive number."
|
||||
},
|
||||
"login": {
|
||||
"title": "User Login",
|
||||
|
||||
@@ -77,7 +77,12 @@
|
||||
"terminalFontSize": "终端字体大小",
|
||||
"errorInvalidFontSize": "无效的字体大小。请输入一个正数。",
|
||||
"terminalFontSizeSaved": "终端字体大小已保存。",
|
||||
"terminalFontSizeSaveFailed": "保存终端字体大小失败: {message}"
|
||||
"terminalFontSizeSaveFailed": "保存终端字体大小失败: {message}",
|
||||
"otherSettings": "其他设置",
|
||||
"editorFontSize": "编辑器字体大小",
|
||||
"editorFontSizeSaved": "编辑器字体大小已保存。",
|
||||
"editorFontSizeSaveFailed": "保存编辑器字体大小失败: {message}",
|
||||
"errorInvalidEditorFontSize": "无效的字体大小。请输入一个正数。"
|
||||
},
|
||||
"login": {
|
||||
"title": "用户登录",
|
||||
|
||||
@@ -64,6 +64,13 @@ export const useAppearanceStore = defineStore('appearance', () => {
|
||||
// 终端背景图片 URL
|
||||
const terminalBackgroundImage = computed(() => appearanceSettings.value.terminalBackgroundImage);
|
||||
|
||||
// 当前编辑器字体大小
|
||||
const currentEditorFontSize = computed<number>(() => {
|
||||
// 提供默认值 14,如果后端没有设置或设置无效
|
||||
const size = appearanceSettings.value.editorFontSize;
|
||||
return typeof size === 'number' && size > 0 ? size : 14;
|
||||
});
|
||||
|
||||
// --- Actions ---
|
||||
|
||||
/**
|
||||
@@ -172,6 +179,14 @@ export const useAppearanceStore = defineStore('appearance', () => {
|
||||
await updateAppearanceSettings({ terminalFontSize: size });
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置编辑器字体大小
|
||||
* @param size 字体大小 (数字)
|
||||
*/
|
||||
async function setEditorFontSize(size: number) {
|
||||
await updateAppearanceSettings({ editorFontSize: size });
|
||||
}
|
||||
|
||||
// --- 终端主题列表管理 Actions ---
|
||||
|
||||
/**
|
||||
@@ -421,7 +436,8 @@ export const useAppearanceStore = defineStore('appearance', () => {
|
||||
activeTerminalThemeId,
|
||||
currentTerminalTheme,
|
||||
currentTerminalFontFamily,
|
||||
currentTerminalFontSize, // <-- 添加
|
||||
currentTerminalFontSize,
|
||||
currentEditorFontSize, // <-- 新增
|
||||
pageBackgroundImage,
|
||||
// pageBackgroundOpacity, // Removed
|
||||
terminalBackgroundImage,
|
||||
@@ -433,7 +449,8 @@ export const useAppearanceStore = defineStore('appearance', () => {
|
||||
resetCustomUiTheme,
|
||||
setActiveTerminalTheme,
|
||||
setTerminalFontFamily,
|
||||
setTerminalFontSize, // <-- 添加
|
||||
setTerminalFontSize,
|
||||
setEditorFontSize, // <-- 新增
|
||||
reloadTerminalThemes,
|
||||
createTerminalTheme,
|
||||
updateTerminalTheme,
|
||||
|
||||
Reference in New Issue
Block a user