feat: 添加调整终端字体大小设置

This commit is contained in:
Baobhan Sith
2025-04-18 09:17:56 +08:00
parent fdc613e12d
commit f8c651dafa
8 changed files with 103 additions and 24 deletions
@@ -16,6 +16,7 @@ const createTableIfNotExists = () => {
custom_ui_theme TEXT,
active_terminal_theme_id TEXT,
terminal_font_family TEXT,
terminal_font_size INTEGER, -- 添加字体大小列
terminal_background_image TEXT,
page_background_image TEXT,
updated_at INTEGER NOT NULL
@@ -39,6 +40,7 @@ const mapRowToAppearanceSettings = (row: any): AppearanceSettings => {
customUiTheme: row.custom_ui_theme,
activeTerminalThemeId: row.active_terminal_theme_id,
terminalFontFamily: row.terminal_font_family,
terminalFontSize: row.terminal_font_size, // 添加字体大小映射
terminalBackgroundImage: row.terminal_background_image,
// terminalBackgroundOpacity: row.terminal_background_opacity, // Removed
pageBackgroundImage: row.page_background_image,
@@ -56,6 +58,7 @@ const getDefaultAppearanceSettings = (): AppearanceSettings => {
customUiTheme: JSON.stringify(defaultUiTheme), // Use default UI theme
activeTerminalThemeId: undefined, // Needs to be set after querying default theme ID
terminalFontFamily: 'Consolas, "Courier New", monospace, "Microsoft YaHei", "微软雅黑"', // Default font
terminalFontSize: 14, // 添加默认字体大小
terminalBackgroundImage: undefined,
// terminalBackgroundOpacity: 1.0, // Removed
pageBackgroundImage: undefined,
@@ -79,17 +82,18 @@ const ensureDefaultSettingsExist = () => {
if (!row) {
const sqlInsert = `
INSERT INTO ${TABLE_NAME} (
id, custom_ui_theme, active_terminal_theme_id, terminal_font_family,
id, custom_ui_theme, active_terminal_theme_id, terminal_font_family, terminal_font_size, -- 添加列
terminal_background_image, -- terminal_background_opacity, -- Removed
page_background_image, -- page_background_opacity, -- Removed
updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?) -- Adjusted placeholder count
) VALUES (?, ?, ?, ?, ?, ?, ?, ?) -- 调整占位符数量
`;
db.run(sqlInsert, [
SETTINGS_ID,
defaults.customUiTheme,
defaults.activeTerminalThemeId, // Initially undefined
defaults.terminalFontFamily,
defaults.terminalFontSize, // 添加默认值参数
defaults.terminalBackgroundImage,
// defaults.terminalBackgroundOpacity, // Removed
defaults.pageBackgroundImage,
@@ -175,8 +179,8 @@ export const updateAppearanceSettings = async (settingsDto: UpdateAppearanceDto)
for (const key in settingsDto) {
if (Object.prototype.hasOwnProperty.call(settingsDto, key)) {
const dbKey = key.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`); // Convert camelCase to snake_case
// Ensure only valid keys are updated (Removed opacity keys)
if (['custom_ui_theme', 'active_terminal_theme_id', 'terminal_font_family', 'terminal_background_image', 'page_background_image'].includes(dbKey)) {
// Ensure only valid keys are updated (Added terminal_font_size)
if (['custom_ui_theme', 'active_terminal_theme_id', 'terminal_font_family', 'terminal_font_size', 'terminal_background_image', 'page_background_image'].includes(dbKey)) {
updates.push(`${dbKey} = ?`);
params.push((settingsDto as any)[key]);
}
@@ -38,6 +38,16 @@ export const updateSettings = async (settingsDto: UpdateAppearanceDto): Promise<
// We just need to ensure the key exists in the DTO if it's meant to be cleared.
}
// 验证 terminalFontSize (如果提供了)
if (settingsDto.terminalFontSize !== undefined && settingsDto.terminalFontSize !== null) {
const size = Number(settingsDto.terminalFontSize);
if (isNaN(size) || size <= 0) {
throw new Error(`无效的终端字体大小: ${settingsDto.terminalFontSize}。必须是一个正数。`);
}
// 可以选择将验证后的数字类型赋值回 DTO,以确保类型正确传递给仓库层
settingsDto.terminalFontSize = size;
}
// TODO: 如果实现了背景图片上传,这里需要处理文件路径或 URL 的验证/保存逻辑
return appearanceRepository.updateAppearanceSettings(settingsDto);
@@ -9,6 +9,7 @@ export interface AppearanceSettings {
customUiTheme?: string; // UI 主题 (CSS 变量 JSON 字符串)
activeTerminalThemeId?: string; // 当前激活的终端主题 ID (对应 terminal_themes 表的 _id)
terminalFontFamily?: string; // 终端字体列表字符串
terminalFontSize?: number; // 终端字体大小 (px)
terminalBackgroundImage?: string; // 终端背景图片 URL 或路径
pageBackgroundImage?: string; // 页面背景图片 URL 或路径
updatedAt?: number;
@@ -15,6 +15,7 @@ const {
activeTerminalThemeId,
availableTerminalThemes,
currentTerminalFontFamily,
currentTerminalFontSize, // <-- 添加
pageBackgroundImage,
// pageBackgroundOpacity, // Removed
terminalBackgroundImage,
@@ -24,6 +25,7 @@ const {
// --- 本地状态用于编辑 ---
const editableUiTheme = ref<Record<string, string>>({});
const editableTerminalFontFamily = ref('');
const editableTerminalFontSize = ref(14); // <-- 添加,默认值 14
// const editablePageBackgroundOpacity = ref(1.0); // Removed
// const editableTerminalBackgroundOpacity = ref(1.0); // Removed
@@ -46,9 +48,11 @@ const saveThemeError = ref<string | null>(null); // 用于显示保存主题时
// 初始化本地编辑状态
const initializeEditableState = () => {
// 深拷贝 UI 主题
// 深拷贝 UI 主题
editableUiTheme.value = JSON.parse(JSON.stringify(currentUiTheme.value || {}));
editableTerminalFontFamily.value = currentTerminalFontFamily.value;
editableTerminalFontSize.value = currentTerminalFontSize.value; // <-- 添加
selectedTerminalThemeId.value = activeTerminalThemeId.value ?? null; // 初始化下拉框
// editablePageBackgroundOpacity.value = pageBackgroundOpacity.value; // Removed
// editableTerminalBackgroundOpacity.value = terminalBackgroundOpacity.value; // Removed
@@ -63,18 +67,20 @@ onMounted(initializeEditableState);
// 监听 store 变化以更新本地状态 (例如重置或外部更改)
// 只监听不需要编辑的状态或用于初始化的状态
watch([
currentUiTheme, currentTerminalFontFamily, activeTerminalThemeId
currentUiTheme, currentTerminalFontFamily, currentTerminalFontSize, activeTerminalThemeId // <-- 添加 currentTerminalFontSize
// pageBackgroundOpacity, terminalBackgroundOpacity // Removed dependencies
], (newVals, oldVals) => {
// 仅当非编辑状态时,或活动主题ID变化时,才同步下拉框和非编辑状态
if (!isEditingTheme.value || newVals[2] !== oldVals[2]) {
// 注意:索引现在需要调整,因为 newVals 数组长度变了
if (!isEditingTheme.value || newVals[3] !== oldVals[3]) { // <-- 索引从 2 改为 3
initializeEditableState();
} else {
// 如果正在编辑,只更新非编辑相关的部分 (例如 UI 主题可以在编辑终端主题时同时更新)
// 如果正在编辑,只更新非编辑相关的部分
editableUiTheme.value = JSON.parse(JSON.stringify(newVals[0] || {}));
editableTerminalFontFamily.value = newVals[1];
// editablePageBackgroundOpacity.value = newVals[3]; // Removed
// editableTerminalBackgroundOpacity.value = newVals[4]; // Removed
editableTerminalFontSize.value = newVals[2]; // <-- 添加
// editablePageBackgroundOpacity.value = newVals[4]; // Removed
// editableTerminalBackgroundOpacity.value = newVals[5]; // Removed
}
}, { deep: true });
@@ -135,6 +141,22 @@ const handleSaveTerminalFont = async () => {
}
};
// 保存终端字体大小
const handleSaveTerminalFontSize = async () => {
try {
const size = Number(editableTerminalFontSize.value);
if (isNaN(size) || size <= 0) {
alert(t('styleCustomizer.errorInvalidFontSize')); // 需要添加翻译
return;
}
await appearanceStore.setTerminalFontSize(size);
alert(t('styleCustomizer.terminalFontSizeSaved')); // 需要添加翻译
} catch (error: any) {
console.error("保存终端字体大小失败:", error);
alert(t('styleCustomizer.terminalFontSizeSaveFailed', { message: error.message })); // 需要添加翻译
}
};
// 更改激活的终端主题
const handleTerminalThemeChange = async () => {
try {
@@ -401,6 +423,13 @@ const formatXtermLabel = (key: keyof ITheme): string => {
</div>
<p class="setting-description">{{ t('styleCustomizer.terminalFontDescription') }}</p>
<!-- 终端字体大小设置 -->
<div class="form-group">
<label for="terminalFontSize">{{ t('styleCustomizer.terminalFontSize') }}:</label> <!-- 需要添加翻译 -->
<input type="number" id="terminalFontSize" v-model.number="editableTerminalFontSize" class="number-input" min="1" />
<button @click="handleSaveTerminalFontSize" class="button-inline">{{ t('common.save') }}</button>
</div>
<hr>
<!-- 终端主题选择与管理 -->
+23 -13
View File
@@ -27,11 +27,11 @@ let terminal: Terminal | null = null;
let fitAddon: FitAddon | null = null;
let resizeObserver: ResizeObserver | null = null;
let debounceTimer: number | null = null; // 用于防抖的计时器 ID
const fontSize = ref(14); // 字体大小状态, 默认为14 (这个可以保留,或者也移到 appearance store)
// const fontSize = ref(14); // 移除本地字体大小状态,将由 store 管理
// --- Appearance Store ---
const appearanceStore = useAppearanceStore();
const { currentTerminalTheme, currentTerminalFontFamily, terminalBackgroundImage } = storeToRefs(appearanceStore); // 获取外观状态 (移除 terminalBackgroundOpacity)
const { currentTerminalTheme, currentTerminalFontFamily, terminalBackgroundImage, currentTerminalFontSize } = storeToRefs(appearanceStore); // <-- 添加 currentTerminalFontSize
// 防抖函数
const debounce = (func: Function, delay: number) => {
@@ -75,7 +75,7 @@ onMounted(() => {
if (terminalRef.value) {
terminal = new Terminal({
cursorBlink: true,
fontSize: fontSize.value, // 初始字体大小
fontSize: currentTerminalFontSize.value, // <-- 使用 store 中的字体大小
fontFamily: currentTerminalFontFamily.value, // 使用 store 中的字体设置
theme: currentTerminalTheme.value, // 使用 store 中的当前 xterm 主题
rows: 24, // 初始行数
@@ -202,6 +202,16 @@ onMounted(() => {
}
});
// 监听字体大小变化
watch(currentTerminalFontSize, (newSize) => {
if (terminal) {
console.log(`[Terminal ${props.sessionId}] 应用新终端字体大小: ${newSize}`);
terminal.options.fontSize = newSize;
// 字体大小变化需要重新 fit
fitAndEmitResizeNow(terminal);
}
});
// 监听背景图片变化
watch(terminalBackgroundImage, () => { // 只监听图片
console.log(`[Terminal Watcher] terminalBackgroundImage changed. New image: ${terminalBackgroundImage.value}`); // 添加日志确认 watcher 触发
@@ -242,17 +252,17 @@ onMounted(() => {
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
}
// 更新终端字体大小
// 直接读取和修改 terminal 实例的字体大小
if (terminal) {
terminal.options.fontSize = fontSize.value;
let newSize;
if (event.deltaY < 0) {
// 向上滚动,增大字体
newSize = Math.min((terminal.options.fontSize ?? currentTerminalFontSize.value) + 1, 40); // 使用当前实例值或 store 值作为基础
} else {
// 向下滚动,减小字体
newSize = Math.max((terminal.options.fontSize ?? currentTerminalFontSize.value) - 1, 8); // 使用当前实例值或 store 值作为基础
}
terminal.options.fontSize = newSize;
// 调整终端大小以适应新的字体大小
fitAddon?.fit();
emit('resize', { cols: terminal.cols, rows: terminal.rows });
+5 -1
View File
@@ -73,7 +73,11 @@
"uiThemeResetFailed": "Failed to reset UI theme: {message}",
"terminalFontSaved": "Terminal font saved.",
"terminalFontSaveFailed": "Failed to save terminal font: {message}",
"setActiveThemeFailed": "Failed to set active terminal theme: {message}"
"setActiveThemeFailed": "Failed to set active terminal theme: {message}",
"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}"
},
"login": {
"title": "User Login",
+5 -1
View File
@@ -73,7 +73,11 @@
"uiThemeResetFailed": "重置界面主题失败: {message}",
"terminalFontSaved": "终端字体已保存。",
"terminalFontSaveFailed": "保存终端字体失败: {message}",
"setActiveThemeFailed": "设置激活终端主题失败: {message}"
"setActiveThemeFailed": "设置激活终端主题失败: {message}",
"terminalFontSize": "终端字体大小",
"errorInvalidFontSize": "无效的字体大小。请输入一个正数。",
"terminalFontSizeSaved": "终端字体大小已保存。",
"terminalFontSizeSaveFailed": "保存终端字体大小失败: {message}"
},
"login": {
"title": "用户登录",
@@ -51,6 +51,13 @@ export const useAppearanceStore = defineStore('appearance', () => {
return appearanceSettings.value.terminalFontFamily || 'Consolas, "Courier New", monospace, "Microsoft YaHei", "微软雅黑"'; // 提供默认值
});
// 当前终端字体大小
const currentTerminalFontSize = computed<number>(() => {
// 提供默认值 14,如果后端没有设置或设置无效
const size = appearanceSettings.value.terminalFontSize;
return typeof size === 'number' && size > 0 ? size : 14;
});
// 页面背景图片 URL
const pageBackgroundImage = computed(() => appearanceSettings.value.pageBackgroundImage);
@@ -157,6 +164,14 @@ export const useAppearanceStore = defineStore('appearance', () => {
await updateAppearanceSettings({ terminalFontFamily: fontFamily });
}
/**
*
* @param size ()
*/
async function setTerminalFontSize(size: number) {
await updateAppearanceSettings({ terminalFontSize: size });
}
// --- 终端主题列表管理 Actions ---
/**
@@ -406,6 +421,7 @@ export const useAppearanceStore = defineStore('appearance', () => {
activeTerminalThemeId,
currentTerminalTheme,
currentTerminalFontFamily,
currentTerminalFontSize, // <-- 添加
pageBackgroundImage,
// pageBackgroundOpacity, // Removed
terminalBackgroundImage,
@@ -417,6 +433,7 @@ export const useAppearanceStore = defineStore('appearance', () => {
resetCustomUiTheme,
setActiveTerminalTheme,
setTerminalFontFamily,
setTerminalFontSize, // <-- 添加
reloadTerminalThemes,
createTerminalTheme,
updateTerminalTheme,