Added key binding service

This commit is contained in:
2025-06-20 13:37:48 +08:00
parent 13072a00a1
commit 85544ba1e4
18 changed files with 1968 additions and 349 deletions

View File

@@ -28,11 +28,6 @@ export class AppConfig {
*/
"appearance": AppearanceConfig;
/**
* 快捷键设置
*/
"keyBindings": KeyBindingsConfig;
/**
* 更新设置
*/
@@ -54,9 +49,6 @@ export class AppConfig {
if (!("appearance" in $$source)) {
this["appearance"] = (new AppearanceConfig());
}
if (!("keyBindings" in $$source)) {
this["keyBindings"] = (new KeyBindingsConfig());
}
if (!("updates" in $$source)) {
this["updates"] = (new UpdatesConfig());
}
@@ -76,7 +68,6 @@ export class AppConfig {
const $$createField2_0 = $$createType2;
const $$createField3_0 = $$createType3;
const $$createField4_0 = $$createType4;
const $$createField5_0 = $$createType5;
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
if ("general" in $$parsedSource) {
$$parsedSource["general"] = $$createField0_0($$parsedSource["general"]);
@@ -87,14 +78,11 @@ export class AppConfig {
if ("appearance" in $$parsedSource) {
$$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"]);
$$parsedSource["updates"] = $$createField3_0($$parsedSource["updates"]);
}
if ("metadata" in $$parsedSource) {
$$parsedSource["metadata"] = $$createField5_0($$parsedSource["metadata"]);
$$parsedSource["metadata"] = $$createField4_0($$parsedSource["metadata"]);
}
return new AppConfig($$parsedSource as Partial<AppConfig>);
}
@@ -139,23 +127,15 @@ export class AppearanceConfig {
* ConfigMetadata 配置元数据
*/
export class ConfigMetadata {
/**
* 配置版本
*/
"version": string;
/**
* 最后更新时间
*/
"lastUpdated": time$0.Time;
"lastUpdated": string;
/** Creates a new ConfigMetadata instance. */
constructor($$source: Partial<ConfigMetadata> = {}) {
if (!("version" in $$source)) {
this["version"] = "";
}
if (!("lastUpdated" in $$source)) {
this["lastUpdated"] = null;
this["lastUpdated"] = "";
}
Object.assign(this, $$source);
@@ -200,7 +180,7 @@ export class Document {
* Creates a new Document instance from a string or object.
*/
static createFrom($$source: any = {}): Document {
const $$createField0_0 = $$createType6;
const $$createField0_0 = $$createType5;
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
if ("meta" in $$parsedSource) {
$$parsedSource["meta"] = $$createField0_0($$parsedSource["meta"]);
@@ -401,7 +381,7 @@ export class GeneralConfig {
* Creates a new GeneralConfig instance from a string or object.
*/
static createFrom($$source: any = {}): GeneralConfig {
const $$createField4_0 = $$createType7;
const $$createField4_0 = $$createType6;
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
if ("globalHotkey" in $$parsedSource) {
$$parsedSource["globalHotkey"] = $$createField4_0($$parsedSource["globalHotkey"]);
@@ -470,25 +450,426 @@ export class HotkeyCombo {
}
/**
* KeyBindingsConfig 快捷键设置配置
* KeyBinding 单个快捷键绑定
*/
export class KeyBindingsConfig {
export class KeyBinding {
/**
* 快捷键唯一标识
*/
"id": string;
/** Creates a new KeyBindingsConfig instance. */
constructor($$source: Partial<KeyBindingsConfig> = {}) {
/**
* 快捷键动作
*/
"action": KeyBindingAction;
/**
* 快捷键分类
*/
"category": KeyBindingCategory;
/**
* 快捷键作用域
*/
"scope": KeyBindingScope;
/**
* 快捷键组合(如 "Mod-f", "Ctrl-Shift-p"
*/
"key": string;
/**
* 是否启用
*/
"enabled": boolean;
/**
* 是否为默认快捷键
*/
"isDefault": boolean;
/** Creates a new KeyBinding instance. */
constructor($$source: Partial<KeyBinding> = {}) {
if (!("id" in $$source)) {
this["id"] = "";
}
if (!("action" in $$source)) {
this["action"] = ("" as KeyBindingAction);
}
if (!("category" in $$source)) {
this["category"] = ("" as KeyBindingCategory);
}
if (!("scope" in $$source)) {
this["scope"] = ("" as KeyBindingScope);
}
if (!("key" in $$source)) {
this["key"] = "";
}
if (!("enabled" in $$source)) {
this["enabled"] = false;
}
if (!("isDefault" in $$source)) {
this["isDefault"] = false;
}
Object.assign(this, $$source);
}
/**
* Creates a new KeyBindingsConfig instance from a string or object.
* Creates a new KeyBinding instance from a string or object.
*/
static createFrom($$source: any = {}): KeyBindingsConfig {
static createFrom($$source: any = {}): KeyBinding {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
return new KeyBindingsConfig($$parsedSource as Partial<KeyBindingsConfig>);
return new KeyBinding($$parsedSource as Partial<KeyBinding>);
}
}
/**
* KeyBindingAction 快捷键动作类型
*/
export enum KeyBindingAction {
/**
* The Go zero value for the underlying type of the enum.
*/
$zero = "",
/**
* 搜索相关
* 显示搜索
*/
ActionShowSearch = "showSearch",
/**
* 隐藏搜索
*/
ActionHideSearch = "hideSearch",
/**
* 查找下一个
*/
ActionFindNext = "findNext",
/**
* 查找上一个
*/
ActionFindPrevious = "findPrevious",
/**
* 显示替换
*/
ActionShowReplace = "showReplace",
/**
* 替换下一个
*/
ActionReplaceNext = "replaceNext",
/**
* 替换全部
*/
ActionReplaceAll = "replaceAll",
/**
* 切换大小写匹配
*/
ActionToggleCase = "toggleCase",
/**
* 切换全词匹配
*/
ActionToggleWholeWord = "toggleWholeWord",
/**
* 切换正则表达式
*/
ActionToggleRegex = "toggleRegex",
/**
* 编辑相关
* 全选
*/
ActionSelectAll = "selectAll",
/**
* 复制
*/
ActionCopy = "copy",
/**
* 剪切
*/
ActionCut = "cut",
/**
* 粘贴
*/
ActionPaste = "paste",
/**
* 撤销
*/
ActionUndo = "undo",
/**
* 重做
*/
ActionRedo = "redo",
/**
* 复制行
*/
ActionDuplicateLine = "duplicateLine",
/**
* 删除行
*/
ActionDeleteLine = "deleteLine",
/**
* 上移行
*/
ActionMoveLineUp = "moveLineUp",
/**
* 下移行
*/
ActionMoveLineDown = "moveLineDown",
/**
* 切换注释
*/
ActionToggleComment = "toggleComment",
/**
* 缩进
*/
ActionIndent = "indent",
/**
* 取消缩进
*/
ActionOutdent = "outdent",
/**
* 代码块相关
* 新建代码块
*/
ActionNewCodeBlock = "newCodeBlock",
/**
* 删除代码块
*/
ActionDeleteCodeBlock = "deleteCodeBlock",
/**
* 选择代码块
*/
ActionSelectCodeBlock = "selectCodeBlock",
/**
* 格式化代码
*/
ActionFormatCode = "formatCode",
/**
* 更改语言
*/
ActionChangeLanguage = "changeLanguage",
/**
* 导航相关
* 跳转到行
*/
ActionGoToLine = "goToLine",
/**
* 折叠所有
*/
ActionFoldAll = "foldAll",
/**
* 展开所有
*/
ActionUnfoldAll = "unfoldAll",
/**
* 切换折叠
*/
ActionToggleFold = "toggleFold",
/**
* 视图相关
* 放大
*/
ActionZoomIn = "zoomIn",
/**
* 缩小
*/
ActionZoomOut = "zoomOut",
/**
* 重置缩放
*/
ActionResetZoom = "resetZoom",
/**
* 切换小地图
*/
ActionToggleMinimap = "toggleMinimap",
/**
* 切换行号
*/
ActionToggleLineNumbers = "toggleLineNumbers",
/**
* 文件相关
* 保存
*/
ActionSave = "save",
};
/**
* KeyBindingCategory 快捷键分类
*/
export enum KeyBindingCategory {
/**
* The Go zero value for the underlying type of the enum.
*/
$zero = "",
/**
* 搜索相关
*/
CategorySearch = "search",
/**
* 编辑相关
*/
CategoryEdit = "edit",
/**
* 代码块相关
*/
CategoryCodeBlock = "codeblock",
/**
* 导航相关
*/
CategoryNavigation = "navigation",
/**
* 视图相关
*/
CategoryView = "view",
/**
* 文件相关
*/
CategoryFile = "file",
/**
* 应用相关
*/
CategoryApp = "app",
};
/**
* KeyBindingConfig 快捷键配置
*/
export class KeyBindingConfig {
/**
* 快捷键列表
*/
"keyBindings": KeyBinding[];
/**
* 配置元数据
*/
"metadata": KeyBindingMetadata;
/** Creates a new KeyBindingConfig instance. */
constructor($$source: Partial<KeyBindingConfig> = {}) {
if (!("keyBindings" in $$source)) {
this["keyBindings"] = [];
}
if (!("metadata" in $$source)) {
this["metadata"] = (new KeyBindingMetadata());
}
Object.assign(this, $$source);
}
/**
* Creates a new KeyBindingConfig instance from a string or object.
*/
static createFrom($$source: any = {}): KeyBindingConfig {
const $$createField0_0 = $$createType8;
const $$createField1_0 = $$createType9;
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
if ("keyBindings" in $$parsedSource) {
$$parsedSource["keyBindings"] = $$createField0_0($$parsedSource["keyBindings"]);
}
if ("metadata" in $$parsedSource) {
$$parsedSource["metadata"] = $$createField1_0($$parsedSource["metadata"]);
}
return new KeyBindingConfig($$parsedSource as Partial<KeyBindingConfig>);
}
}
/**
* KeyBindingMetadata 快捷键配置元数据
*/
export class KeyBindingMetadata {
/**
* 最后更新时间
*/
"lastUpdated": string;
/** Creates a new KeyBindingMetadata instance. */
constructor($$source: Partial<KeyBindingMetadata> = {}) {
if (!("lastUpdated" in $$source)) {
this["lastUpdated"] = "";
}
Object.assign(this, $$source);
}
/**
* Creates a new KeyBindingMetadata instance from a string or object.
*/
static createFrom($$source: any = {}): KeyBindingMetadata {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
return new KeyBindingMetadata($$parsedSource as Partial<KeyBindingMetadata>);
}
}
/**
* KeyBindingScope 快捷键作用域
*/
export enum KeyBindingScope {
/**
* The Go zero value for the underlying type of the enum.
*/
$zero = "",
/**
* 全局作用域
*/
ScopeGlobal = "global",
/**
* 编辑器作用域
*/
ScopeEditor = "editor",
/**
* 搜索面板作用域
*/
ScopeSearch = "search",
};
/**
* LanguageType 语言类型定义
*/
@@ -578,8 +959,10 @@ export class UpdatesConfig {
const $$createType0 = GeneralConfig.createFrom;
const $$createType1 = EditingConfig.createFrom;
const $$createType2 = AppearanceConfig.createFrom;
const $$createType3 = KeyBindingsConfig.createFrom;
const $$createType4 = UpdatesConfig.createFrom;
const $$createType5 = ConfigMetadata.createFrom;
const $$createType6 = DocumentMeta.createFrom;
const $$createType7 = HotkeyCombo.createFrom;
const $$createType3 = UpdatesConfig.createFrom;
const $$createType4 = ConfigMetadata.createFrom;
const $$createType5 = DocumentMeta.createFrom;
const $$createType6 = HotkeyCombo.createFrom;
const $$createType7 = KeyBinding.createFrom;
const $$createType8 = $Create.Array($$createType7);
const $$createType9 = KeyBindingMetadata.createFrom;

View File

@@ -5,6 +5,7 @@ import * as ConfigService from "./configservice.js";
import * as DialogService from "./dialogservice.js";
import * as DocumentService from "./documentservice.js";
import * as HotkeyService from "./hotkeyservice.js";
import * as KeyBindingService from "./keybindingservice.js";
import * as MigrationService from "./migrationservice.js";
import * as SystemService from "./systemservice.js";
import * as TrayService from "./trayservice.js";
@@ -13,6 +14,7 @@ export {
DialogService,
DocumentService,
HotkeyService,
KeyBindingService,
MigrationService,
SystemService,
TrayService

View File

@@ -0,0 +1,180 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
/**
* KeyBindingService 快捷键管理服务
* @module
*/
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import {Call as $Call, Create as $Create} from "@wailsio/runtime";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: Unused imports
import * as models$0 from "../models/models.js";
/**
* DisableKeyBinding 禁用快捷键
*/
export function DisableKeyBinding(id: string): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(1594003006, id) as any;
return $resultPromise;
}
/**
* EnableKeyBinding 启用快捷键
*/
export function EnableKeyBinding(id: string): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(1462644129, id) as any;
return $resultPromise;
}
/**
* ExportKeyBindings 导出快捷键配置
*/
export function ExportKeyBindings(): Promise<models$0.KeyBinding[]> & { cancel(): void } {
let $resultPromise = $Call.ByID(4089030977) as any;
let $typingPromise = $resultPromise.then(($result: any) => {
return $$createType1($result);
}) as any;
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
return $typingPromise;
}
/**
* GetAllKeyBindings 获取所有快捷键配置
*/
export function GetAllKeyBindings(): Promise<models$0.KeyBinding[]> & { cancel(): void } {
let $resultPromise = $Call.ByID(1633502882) as any;
let $typingPromise = $resultPromise.then(($result: any) => {
return $$createType1($result);
}) as any;
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
return $typingPromise;
}
/**
* GetKeyBindingByAction 根据动作获取快捷键
*/
export function GetKeyBindingByAction(action: models$0.KeyBindingAction): Promise<models$0.KeyBinding | null> & { cancel(): void } {
let $resultPromise = $Call.ByID(752637777, action) as any;
let $typingPromise = $resultPromise.then(($result: any) => {
return $$createType2($result);
}) as any;
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
return $typingPromise;
}
/**
* GetKeyBindingByID 根据ID获取快捷键
*/
export function GetKeyBindingByID(id: string): Promise<models$0.KeyBinding | null> & { cancel(): void } {
let $resultPromise = $Call.ByID(1578192526, id) as any;
let $typingPromise = $resultPromise.then(($result: any) => {
return $$createType2($result);
}) as any;
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
return $typingPromise;
}
/**
* GetKeyBindingCategories 获取所有快捷键分类
*/
export function GetKeyBindingCategories(): Promise<models$0.KeyBindingCategory[]> & { cancel(): void } {
let $resultPromise = $Call.ByID(3141399810) as any;
let $typingPromise = $resultPromise.then(($result: any) => {
return $$createType3($result);
}) as any;
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
return $typingPromise;
}
/**
* GetKeyBindingConfig 获取完整快捷键配置
*/
export function GetKeyBindingConfig(): Promise<models$0.KeyBindingConfig | null> & { cancel(): void } {
let $resultPromise = $Call.ByID(3804318356) as any;
let $typingPromise = $resultPromise.then(($result: any) => {
return $$createType5($result);
}) as any;
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
return $typingPromise;
}
/**
* GetKeyBindingScopes 获取所有快捷键作用域
*/
export function GetKeyBindingScopes(): Promise<models$0.KeyBindingScope[]> & { cancel(): void } {
let $resultPromise = $Call.ByID(2984736455) as any;
let $typingPromise = $resultPromise.then(($result: any) => {
return $$createType6($result);
}) as any;
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
return $typingPromise;
}
/**
* GetKeyBindingsByCategory 根据分类获取快捷键
*/
export function GetKeyBindingsByCategory(category: models$0.KeyBindingCategory): Promise<models$0.KeyBinding[]> & { cancel(): void } {
let $resultPromise = $Call.ByID(1686146606, category) as any;
let $typingPromise = $resultPromise.then(($result: any) => {
return $$createType1($result);
}) as any;
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
return $typingPromise;
}
/**
* GetKeyBindingsByScope 根据作用域获取快捷键
*/
export function GetKeyBindingsByScope(scope: models$0.KeyBindingScope): Promise<models$0.KeyBinding[]> & { cancel(): void } {
let $resultPromise = $Call.ByID(1179712594, scope) as any;
let $typingPromise = $resultPromise.then(($result: any) => {
return $$createType1($result);
}) as any;
$typingPromise.cancel = $resultPromise.cancel.bind($resultPromise);
return $typingPromise;
}
/**
* ImportKeyBindings 导入快捷键配置
*/
export function ImportKeyBindings(keyBindings: models$0.KeyBinding[]): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(642201520, keyBindings) as any;
return $resultPromise;
}
/**
* ResetAllKeyBindings 重置所有快捷键到默认值
*/
export function ResetAllKeyBindings(): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(2771372645) as any;
return $resultPromise;
}
/**
* ResetKeyBinding 重置快捷键到默认值
*/
export function ResetKeyBinding(id: string): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(3466323405, id) as any;
return $resultPromise;
}
/**
* UpdateKeyBinding 更新快捷键
*/
export function UpdateKeyBinding(id: string, newKey: string): Promise<void> & { cancel(): void } {
let $resultPromise = $Call.ByID(1469368983, id, newKey) as any;
return $resultPromise;
}
// Private type creation functions
const $$createType0 = models$0.KeyBinding.createFrom;
const $$createType1 = $Create.Array($$createType0);
const $$createType2 = $Create.Nullable($$createType0);
const $$createType3 = $Create.Array($Create.Any);
const $$createType4 = models$0.KeyBindingConfig.createFrom;
const $$createType5 = $Create.Nullable($$createType4);
const $$createType6 = $Create.Array($Create.Any);

View File

@@ -9,7 +9,7 @@ import {
LanguageType,
SystemThemeType,
TabType,
} from '../../bindings/voidraft/internal/models/models';
} from '@/../bindings/voidraft/internal/models/models';
import {useI18n} from 'vue-i18n';
import {useErrorHandler} from '@/utils/errorHandler';
import {ConfigUtils} from '@/utils/configUtils';
@@ -47,27 +47,27 @@ type NumberConfigKey = 'fontSize' | 'tabSize' | 'lineHeight';
// 配置键映射
const GENERAL_CONFIG_KEY_MAP: GeneralConfigKeyMap = {
alwaysOnTop: 'general.always_on_top',
dataPath: 'general.data_path',
enableSystemTray: 'general.enable_system_tray',
enableGlobalHotkey: 'general.enable_global_hotkey',
globalHotkey: 'general.global_hotkey'
alwaysOnTop: 'general.alwaysOnTop',
dataPath: 'general.dataPath',
enableSystemTray: 'general.enableSystemTray',
enableGlobalHotkey: 'general.enableGlobalHotkey',
globalHotkey: 'general.globalHotkey'
} as const;
const EDITING_CONFIG_KEY_MAP: EditingConfigKeyMap = {
fontSize: 'editing.font_size',
fontFamily: 'editing.font_family',
fontWeight: 'editing.font_weight',
lineHeight: 'editing.line_height',
enableTabIndent: 'editing.enable_tab_indent',
tabSize: 'editing.tab_size',
tabType: 'editing.tab_type',
autoSaveDelay: 'editing.auto_save_delay'
fontSize: 'editing.fontSize',
fontFamily: 'editing.fontFamily',
fontWeight: 'editing.fontWeight',
lineHeight: 'editing.lineHeight',
enableTabIndent: 'editing.enableTabIndent',
tabSize: 'editing.tabSize',
tabType: 'editing.tabType',
autoSaveDelay: 'editing.autoSaveDelay'
} as const;
const APPEARANCE_CONFIG_KEY_MAP: AppearanceConfigKeyMap = {
language: 'appearance.language',
systemTheme: 'appearance.system_theme'
systemTheme: 'appearance.systemTheme'
} as const;
// 配置限制
@@ -141,11 +141,9 @@ const DEFAULT_CONFIG: AppConfig = {
language: LanguageType.LangZhCN,
systemTheme: SystemThemeType.SystemThemeDark
},
keyBindings: {},
updates: {},
metadata: {
version: '1.0.0',
lastUpdated: null
lastUpdated: new Date().toString()
}
};
@@ -226,7 +224,6 @@ export const useConfigStore = defineStore('config', () => {
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);
}

View File

@@ -83,7 +83,7 @@ const goBackToEditor = async () => {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
.settings-sidebar {
width: 200px;
width: 180px;
height: 100%;
background-color: var(--settings-card-bg);
border-right: 1px solid var(--settings-border);
@@ -92,7 +92,7 @@ const goBackToEditor = async () => {
box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1);
.settings-header {
padding: 20px 16px;
padding: 16px 14px;
border-bottom: 1px solid var(--settings-border);
background-color: var(--settings-card-bg);
@@ -125,7 +125,7 @@ const goBackToEditor = async () => {
}
h1 {
font-size: 18px;
font-size: 16px;
font-weight: 600;
margin: 0;
color: var(--settings-text);
@@ -138,10 +138,10 @@ const goBackToEditor = async () => {
padding: 10px 0;
overflow-y: auto;
.nav-item {
.nav-item {
display: flex;
align-items: center;
padding: 12px 16px;
padding: 10px 14px;
cursor: pointer;
transition: all 0.2s ease;
border-left: 3px solid transparent;
@@ -157,19 +157,19 @@ const goBackToEditor = async () => {
}
.nav-icon {
margin-right: 10px;
font-size: 16px;
margin-right: 8px;
font-size: 14px;
opacity: 0.9;
}
.nav-text {
font-size: 14px;
font-size: 13px;
}
}
}
.settings-footer {
padding: 12px 16px 16px 16px;
padding: 10px 14px 14px 14px;
border-top: 1px solid var(--settings-border);
background-color: var(--settings-card-bg);
@@ -179,7 +179,7 @@ const goBackToEditor = async () => {
gap: 8px;
.section-title {
font-size: 10px;
font-size: 9px;
color: var(--settings-text-secondary);
font-weight: 500;
margin-bottom: 0;
@@ -193,7 +193,7 @@ const goBackToEditor = async () => {
.settings-content {
flex: 1;
height: 100%;
padding: 24px 24px 48px 24px;
padding: 20px 20px 40px 20px;
overflow-y: auto;
background-color: var(--settings-bg);
}

View File

@@ -20,7 +20,7 @@ defineProps<{
<style scoped lang="scss">
.setting-item {
display: flex;
padding: 14px 0;
padding: 12px 0;
border-bottom: 1px solid var(--settings-border);
transition: background-color 0.15s ease;
@@ -35,24 +35,24 @@ defineProps<{
.setting-info {
flex: 1;
padding-right: 20px;
padding-right: 16px;
.setting-title {
font-size: 14px;
font-size: 13px;
font-weight: 500;
margin-bottom: 6px;
margin-bottom: 4px;
color: var(--settings-text);
}
.setting-description {
font-size: 12px;
font-size: 11px;
color: var(--settings-text-secondary);
line-height: 1.5;
line-height: 1.4;
}
}
.setting-control {
width: 200px;
width: 180px;
display: flex;
align-items: center;
justify-content: flex-end;

View File

@@ -15,7 +15,7 @@ defineProps<{
<style scoped lang="scss">
.setting-section {
margin-bottom: 30px;
margin-bottom: 24px;
background-color: var(--settings-card-bg);
border-radius: 6px;
overflow: hidden;
@@ -23,17 +23,17 @@ defineProps<{
border: 1px solid var(--settings-border);
.section-title {
font-size: 14px;
font-size: 13px;
font-weight: 600;
margin: 0;
padding: 12px 16px;
padding: 10px 14px;
background-color: var(--settings-hover);
color: var(--settings-text);
border-bottom: 1px solid var(--settings-border);
}
.section-content {
padding: 8px 16px;
padding: 6px 14px;
}
}
</style>

View File

@@ -1,29 +1,45 @@
<script setup lang="ts">
import { nextTick } from 'vue';
const props = defineProps<{
modelValue: boolean;
disabled?: boolean;
}>();
const emit = defineEmits<{
'update:modelValue': [value: boolean]
}>();
const toggle = () => {
emit('update:modelValue', !props.modelValue);
const toggle = async () => {
if (props.disabled) return;
const newValue = !props.modelValue;
emit('update:modelValue', newValue);
// 确保DOM更新
await nextTick();
};
</script>
<template>
<div class="toggle-switch" :class="{ active: modelValue }" @click="toggle">
<div
class="toggle-switch"
:class="{
active: modelValue,
disabled: disabled
}"
@click="toggle"
>
<div class="toggle-handle"></div>
</div>
</template>
<style scoped lang="scss">
.toggle-switch {
width: 40px;
height: 20px;
width: 36px;
height: 18px;
background-color: var(--settings-input-border);
border-radius: 10px;
border-radius: 9px;
position: relative;
cursor: pointer;
transition: background-color 0.2s;
@@ -33,17 +49,30 @@ const toggle = () => {
background-color: #4a9eff;
.toggle-handle {
transform: translateX(20px);
transform: translateX(18px);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}
}
&.disabled {
opacity: 0.5;
cursor: not-allowed;
&:hover {
background-color: var(--settings-input-border);
}
&.active:hover {
background-color: #4a9eff;
}
}
.toggle-handle {
position: absolute;
top: 2px;
left: 2px;
width: 16px;
height: 16px;
width: 14px;
height: 14px;
background-color: var(--settings-text);
border-radius: 50%;
transition: all 0.2s ease;

View File

@@ -79,19 +79,19 @@ const updateSystemTheme = async (event: Event) => {
}
.select-input {
min-width: 150px;
padding: 8px 12px;
min-width: 140px;
padding: 6px 10px;
border: 1px solid var(--settings-input-border);
border-radius: 4px;
background-color: var(--settings-input-bg);
color: var(--settings-text);
font-size: 13px;
font-size: 12px;
appearance: none;
background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23666666' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
background-repeat: no-repeat;
background-position: right 8px center;
background-size: 16px;
padding-right: 30px;
background-position: right 6px center;
background-size: 14px;
padding-right: 26px;
transition: border-color 0.2s ease;
&:focus {

View File

@@ -123,7 +123,12 @@ const handleToggleTabType = async () => {
// 创建双向绑定的计算属性
const enableTabIndent = computed({
get: () => configStore.config.editing.enableTabIndent,
set: (value: boolean) => configStore.setEnableTabIndent(value)
set: async (value: boolean) => {
await safeCall(
() => configStore.setEnableTabIndent(value),
'config.tabIndentToggleFailed'
);
}
});
// 保存选项处理器
@@ -138,31 +143,7 @@ const handleAutoSaveDelayChange = async (event: Event) => {
}
};
// 动态字体预览文本
const fontPreviewText = computed(() => {
const currentFont = configStore.config.editing.fontFamily;
// 根据字体类型返回不同的预览文本
if (currentFont.includes('HarmonyOS')) {
return '鸿蒙字体测试';
} else if (currentFont.includes('Microsoft YaHei')) {
return '微软雅黑测试';
} else if (currentFont.includes('PingFang')) {
return '苹方字体测试';
} else if (currentFont.includes('JetBrains')) {
return 'JetBrains Mono';
} else if (currentFont.includes('Fira Code')) {
return 'Fira Code Test';
} else if (currentFont.includes('Source Code')) {
return 'Source Code Pro';
} else if (currentFont.includes('Cascadia')) {
return 'Cascadia Code';
} else if (currentFont.includes('SF Mono') || currentFont.includes('Monaco')) {
return 'System Monospace';
} else {
return 'Font Preview';
}
});
</script>
<template>
@@ -228,20 +209,7 @@ const fontPreviewText = computed(() => {
</div>
</SettingItem>
<div class="font-preview" :style="{
fontSize: `${configStore.config.editing.fontSize}px`,
fontFamily: configStore.config.editing.fontFamily,
fontWeight: configStore.config.editing.fontWeight,
lineHeight: configStore.config.editing.lineHeight
}">
<div class="preview-label">字体预览</div>
<div class="preview-text">
<span>function example() {</span>
<span class="indent">console.log("Hello, 世界!");</span>
<span class="indent">const message = "{{ fontPreviewText }}";</span>
<span>}</span>
</div>
</div>
</SettingSection>
<SettingSection :title="t('settings.tabSettings')">
@@ -314,7 +282,7 @@ const fontPreviewText = computed(() => {
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
font-size: 12px;
transition: all 0.2s ease;
&:hover:not(:disabled) {
@@ -335,7 +303,7 @@ const fontPreviewText = computed(() => {
span {
min-width: 50px;
text-align: center;
font-size: 14px;
font-size: 12px;
color: var(--settings-text);
background-color: var(--settings-input-bg);
border: 1px solid var(--settings-input-border);
@@ -344,65 +312,7 @@ const fontPreviewText = computed(() => {
}
}
.font-size-preview {
margin: 15px 0 5px 20px;
padding: 15px;
background-color: var(--settings-card-bg);
border: 1px solid var(--settings-border);
border-radius: 4px;
font-family: 'Consolas', 'Courier New', monospace;
.preview-label {
font-size: 12px;
color: var(--text-muted);
margin-bottom: 8px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
.preview-text {
display: flex;
flex-direction: column;
span {
line-height: 1.4;
color: var(--settings-text-secondary);
}
.indent {
padding-left: 20px;
color: #4a9eff;
}
}
}
.font-preview {
margin: 15px 0 5px 20px;
padding: 15px;
background-color: var(--settings-card-bg);
border: 1px solid var(--settings-border);
border-radius: 4px;
.preview-label {
font-size: 12px;
color: var(--text-muted);
margin-bottom: 8px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
.preview-text {
display: flex;
flex-direction: column;
span {
color: var(--settings-text-secondary);
}
.indent {
padding-left: 20px;
color: #4a9eff;
}
}
}
.font-family-select,
.font-weight-select {
@@ -412,7 +322,7 @@ const fontPreviewText = computed(() => {
border-radius: 4px;
background-color: var(--settings-input-bg);
color: var(--settings-text);
font-size: 13px;
font-size: 12px;
cursor: pointer;
&:focus {
@@ -439,7 +349,7 @@ const fontPreviewText = computed(() => {
border-radius: 4px;
color: var(--settings-text);
cursor: pointer;
font-size: 13px;
font-size: 12px;
text-align: center;
transition: all 0.2s ease;
@@ -460,7 +370,7 @@ const fontPreviewText = computed(() => {
border-radius: 4px;
background-color: var(--settings-input-bg);
color: var(--settings-text);
font-size: 13px;
font-size: 12px;
&:focus {
outline: none;

View File

@@ -472,7 +472,7 @@ onUnmounted(() => {
border: 1px solid var(--settings-input-border);
border-radius: 4px;
color: var(--settings-text-secondary);
font-size: 13px;
font-size: 12px;
transition: all 0.2s ease;
&:hover {
@@ -493,10 +493,10 @@ onUnmounted(() => {
padding: 8px 12px;
background-color: var(--settings-input-bg);
border: 1px solid var(--settings-input-border);
border-radius: 4px;
color: var(--settings-text);
font-size: 13px;
appearance: none;
border-radius: 4px;
color: var(--settings-text);
font-size: 12px;
appearance: none;
background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23999999' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
background-repeat: no-repeat;
background-position: right 8px center;
@@ -530,17 +530,17 @@ onUnmounted(() => {
border-radius: 4px;
margin-top: 8px;
.preview-label {
font-size: 12px;
color: var(--settings-text-secondary);
}
.preview-hotkey {
font-size: 13px;
color: var(--settings-text);
font-weight: 500;
font-family: 'Consolas', 'Courier New', monospace;
}
.preview-label {
font-size: 11px;
color: var(--settings-text-secondary);
}
.preview-hotkey {
font-size: 12px;
color: var(--settings-text);
font-weight: 500;
font-family: 'Consolas', 'Courier New', monospace;
}
}
}
@@ -558,7 +558,7 @@ onUnmounted(() => {
margin-bottom: 12px;
.setting-title {
font-size: 14px;
font-size: 13px;
font-weight: 500;
color: var(--settings-text);
}
@@ -583,7 +583,7 @@ onUnmounted(() => {
border: 1px solid var(--settings-input-border);
border-radius: 4px;
color: var(--settings-text);
font-size: 13px;
font-size: 12px;
line-height: 1.2;
transition: all 0.2s ease;
cursor: pointer;

View File

@@ -132,7 +132,7 @@ const handleKeyDown = (event: KeyboardEvent, binding: KeyBinding) => {
padding: 0 0 10px 0;
border-bottom: 1px solid var(--settings-border);
color: var(--text-muted);
font-size: 13px;
font-size: 12px;
font-weight: 500;
}
@@ -159,7 +159,7 @@ const handleKeyDown = (event: KeyboardEvent, binding: KeyBinding) => {
.command-col {
flex: 1;
padding-right: 10px;
font-size: 14px;
font-size: 13px;
color: var(--settings-text);
}
@@ -176,9 +176,9 @@ const handleKeyDown = (event: KeyboardEvent, binding: KeyBinding) => {
.key-badge {
background-color: var(--settings-input-bg);
padding: 3px 8px;
padding: 2px 6px;
border-radius: 3px;
font-size: 12px;
font-size: 11px;
border: 1px solid var(--settings-input-border);
color: var(--settings-text);
}
@@ -195,7 +195,7 @@ const handleKeyDown = (event: KeyboardEvent, binding: KeyBinding) => {
border-radius: 4px;
color: var(--settings-text);
cursor: pointer;
font-size: 13px;
font-size: 12px;
transition: all 0.2s ease;
&:hover {
@@ -217,6 +217,6 @@ const handleKeyDown = (event: KeyboardEvent, binding: KeyBinding) => {
color: var(--text-muted);
text-align: center;
font-style: italic;
font-size: 14px;
font-size: 13px;
}
</style>

View File

@@ -103,7 +103,7 @@ const downloadUpdate = () => {
margin-bottom: 20px;
.current-version {
font-size: 14px;
font-size: 13px;
.label {
color: var(--text-muted);
@@ -123,7 +123,7 @@ const downloadUpdate = () => {
border-radius: 4px;
color: var(--settings-text);
cursor: pointer;
font-size: 13px;
font-size: 12px;
transition: all 0.2s ease;
display: flex;
align-items: center;
@@ -172,7 +172,7 @@ const downloadUpdate = () => {
margin-bottom: 16px;
.update-title {
font-size: 14px;
font-size: 13px;
font-weight: 500;
color: #4a9eff;
}
@@ -184,7 +184,7 @@ const downloadUpdate = () => {
border-radius: 4px;
color: #ffffff;
cursor: pointer;
font-size: 13px;
font-size: 12px;
transition: all 0.2s ease;
&:hover {
@@ -199,7 +199,7 @@ const downloadUpdate = () => {
.update-notes {
.notes-title {
font-size: 13px;
font-size: 12px;
color: var(--settings-text-secondary);
margin-bottom: 8px;
}
@@ -209,7 +209,7 @@ const downloadUpdate = () => {
padding-left: 20px;
li {
font-size: 13px;
font-size: 12px;
color: var(--settings-text-secondary);
margin-bottom: 6px;