diff --git a/frontend/bindings/voidraft/internal/models/models.ts b/frontend/bindings/voidraft/internal/models/models.ts index 97f03c6..633f115 100644 --- a/frontend/bindings/voidraft/internal/models/models.ts +++ b/frontend/bindings/voidraft/internal/models/models.ts @@ -477,84 +477,6 @@ export enum ExtensionID { ExtensionCodeBlock = "codeBlock", }; -/** - * ExtensionMetadata 扩展配置元数据 - */ -export class ExtensionMetadata { - /** - * 配置版本 - */ - "version": string; - - /** - * 最后更新时间 - */ - "lastUpdated": string; - - /** Creates a new ExtensionMetadata instance. */ - constructor($$source: Partial = {}) { - if (!("version" in $$source)) { - this["version"] = ""; - } - if (!("lastUpdated" in $$source)) { - this["lastUpdated"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new ExtensionMetadata instance from a string or object. - */ - static createFrom($$source: any = {}): ExtensionMetadata { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new ExtensionMetadata($$parsedSource as Partial); - } -} - -/** - * ExtensionSettings 扩展设置配置 - */ -export class ExtensionSettings { - /** - * 扩展列表 - */ - "extensions": Extension[]; - - /** - * 配置元数据 - */ - "metadata": ExtensionMetadata; - - /** Creates a new ExtensionSettings instance. */ - constructor($$source: Partial = {}) { - if (!("extensions" in $$source)) { - this["extensions"] = []; - } - if (!("metadata" in $$source)) { - this["metadata"] = (new ExtensionMetadata()); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new ExtensionSettings instance from a string or object. - */ - static createFrom($$source: any = {}): ExtensionSettings { - const $$createField0_0 = $$createType9; - const $$createField1_0 = $$createType10; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("extensions" in $$parsedSource) { - $$parsedSource["extensions"] = $$createField0_0($$parsedSource["extensions"]); - } - if ("metadata" in $$parsedSource) { - $$parsedSource["metadata"] = $$createField1_0($$parsedSource["metadata"]); - } - return new ExtensionSettings($$parsedSource as Partial); - } -} - /** * GeneralConfig 通用设置配置 */ @@ -618,7 +540,7 @@ export class GeneralConfig { * Creates a new GeneralConfig instance from a string or object. */ static createFrom($$source: any = {}): GeneralConfig { - const $$createField5_0 = $$createType11; + const $$createField5_0 = $$createType8; let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; if ("globalHotkey" in $$parsedSource) { $$parsedSource["globalHotkey"] = $$createField5_0($$parsedSource["globalHotkey"]); @@ -1095,8 +1017,8 @@ export class KeyBindingConfig { * Creates a new KeyBindingConfig instance from a string or object. */ static createFrom($$source: any = {}): KeyBindingConfig { - const $$createField0_0 = $$createType13; - const $$createField1_0 = $$createType14; + const $$createField0_0 = $$createType10; + const $$createField1_0 = $$createType11; let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; if ("keyBindings" in $$parsedSource) { $$parsedSource["keyBindings"] = $$createField0_0($$parsedSource["keyBindings"]); @@ -1257,10 +1179,7 @@ var $$createType6 = (function $$initCreateType6(...args): any { return $$createType6(...args); }); const $$createType7 = $Create.Map($Create.Any, $Create.Any); -const $$createType8 = Extension.createFrom; -const $$createType9 = $Create.Array($$createType8); -const $$createType10 = ExtensionMetadata.createFrom; -const $$createType11 = HotkeyCombo.createFrom; -const $$createType12 = KeyBinding.createFrom; -const $$createType13 = $Create.Array($$createType12); -const $$createType14 = KeyBindingMetadata.createFrom; +const $$createType8 = HotkeyCombo.createFrom; +const $$createType9 = KeyBinding.createFrom; +const $$createType10 = $Create.Array($$createType9); +const $$createType11 = KeyBindingMetadata.createFrom; diff --git a/frontend/bindings/voidraft/internal/services/extensionservice.ts b/frontend/bindings/voidraft/internal/services/extensionservice.ts index 93ebc0b..cd086ac 100644 --- a/frontend/bindings/voidraft/internal/services/extensionservice.ts +++ b/frontend/bindings/voidraft/internal/services/extensionservice.ts @@ -14,22 +14,6 @@ import {Call as $Call, Create as $Create} from "@wailsio/runtime"; // @ts-ignore: Unused imports import * as models$0 from "../models/models.js"; -/** - * DisableExtension 禁用扩展 - */ -export function DisableExtension(id: models$0.ExtensionID): Promise & { cancel(): void } { - let $resultPromise = $Call.ByID(2040844784, id) as any; - return $resultPromise; -} - -/** - * EnableExtension 启用扩展 - */ -export function EnableExtension(id: models$0.ExtensionID): Promise & { cancel(): void } { - let $resultPromise = $Call.ByID(2926319443, id) as any; - return $resultPromise; -} - /** * GetAllExtensions 获取所有扩展配置 */ @@ -42,18 +26,6 @@ export function GetAllExtensions(): Promise & { cancel(): return $typingPromise; } -/** - * GetExtensionSettings 获取完整扩展配置 - */ -export function GetExtensionSettings(): Promise & { cancel(): void } { - let $resultPromise = $Call.ByID(2127854337) as any; - let $typingPromise = $resultPromise.then(($result: any) => { - return $$createType3($result); - }) as any; - $typingPromise.cancel = $resultPromise.cancel.bind($resultPromise); - return $typingPromise; -} - /** * ResetAllExtensionsToDefault 重置所有扩展到默认状态 */ @@ -78,6 +50,14 @@ export function ServiceShutdown(): Promise & { cancel(): void } { return $resultPromise; } +/** + * UpdateExtensionEnabled 更新扩展启用状态 + */ +export function UpdateExtensionEnabled(id: models$0.ExtensionID, enabled: boolean): Promise & { cancel(): void } { + let $resultPromise = $Call.ByID(1067300094, id, enabled) as any; + return $resultPromise; +} + /** * UpdateExtensionState 更新扩展状态 */ @@ -89,5 +69,3 @@ export function UpdateExtensionState(id: models$0.ExtensionID, enabled: boolean, // Private type creation functions const $$createType0 = models$0.Extension.createFrom; const $$createType1 = $Create.Array($$createType0); -const $$createType2 = models$0.ExtensionSettings.createFrom; -const $$createType3 = $Create.Nullable($$createType2); diff --git a/frontend/src/i18n/locales/en-US.ts b/frontend/src/i18n/locales/en-US.ts index 9db271e..02c26a2 100644 --- a/frontend/src/i18n/locales/en-US.ts +++ b/frontend/src/i18n/locales/en-US.ts @@ -148,6 +148,75 @@ export default { upToDate: 'You are using the latest version', viewUpdate: 'View Update', releaseNotes: 'Release Notes', - networkError: 'Network connection error, please check your network settings' + networkError: 'Network connection error, please check your network settings', + extensions: 'Extensions', + extensionsPage: { + loading: 'Loading', + categoryEditing: 'Editing Enhancement', + categoryUI: 'UI Enhancement', + categoryTools: 'Tools', + configuration: 'Configuration', + resetToDefault: 'Reset to Default Configuration', + minimap: { + displayText: 'Display Text', + displayTextCharacters: 'Characters', + displayTextBlocks: 'Blocks', + showOverlay: 'Show Overlay', + showOverlayAlways: 'Always', + showOverlayHover: 'On Hover', + showOverlayNever: 'Never', + autohide: 'Auto Hide' + }, + codeBlast: { + effect: 'Effect Type', + effectParticles: 'Particle Effect', + effectExplosion: 'Explosion Effect', + shake: 'Shake Effect', + maxParticles: 'Max Particles', + shakeIntensity: 'Shake Intensity' + }, + codeBlock: { + showBackground: 'Show Background', + enableAutoDetection: 'Enable Auto Detection' + } + } + }, + extensions: { + rainbowBrackets: { + name: 'Rainbow Brackets', + description: 'Display nested brackets in different colors' + }, + hyperlink: { + name: 'Hyperlink', + description: 'Recognize and make hyperlinks clickable' + }, + colorSelector: { + name: 'Color Selector', + description: 'Visual color picker and color value display' + }, + minimap: { + name: 'Minimap', + description: 'Display minimap overview of the document' + }, + codeBlast: { + name: 'Code Blast', + description: 'Animated effects while typing' + }, + search: { + name: 'Search', + description: 'Text search and replace functionality' + }, + codeBlock: { + name: 'Code Block', + description: 'Code block syntax highlighting and formatting' + }, + fold: { + name: 'Code Folding', + description: 'Collapse and expand code sections for better readability' + }, + textHighlight: { + name: 'Text Highlight', + description: 'Highlight text selections and search matches' + } } }; \ No newline at end of file diff --git a/frontend/src/i18n/locales/zh-CN.ts b/frontend/src/i18n/locales/zh-CN.ts index d102e8c..44f0739 100644 --- a/frontend/src/i18n/locales/zh-CN.ts +++ b/frontend/src/i18n/locales/zh-CN.ts @@ -98,6 +98,7 @@ export default { general: '常规', editing: '编辑器', appearance: '外观', + extensions: '扩展', keyBindings: '快捷键', updates: '更新', reset: '重置', @@ -148,6 +149,74 @@ export default { upToDate: '您正在使用最新版本', viewUpdate: '查看更新', releaseNotes: '更新内容', - networkError: '网络连接错误,请检查网络设置' + networkError: '网络连接错误,请检查网络设置', + extensionsPage: { + loading: '加载中', + categoryEditing: '编辑增强', + categoryUI: '界面增强', + categoryTools: '工具扩展', + configuration: '配置', + resetToDefault: '重置为默认配置', + minimap: { + displayText: '显示文本', + displayTextCharacters: '字符', + displayTextBlocks: '块', + showOverlay: '显示覆盖层', + showOverlayAlways: '始终', + showOverlayHover: '悬停时', + showOverlayNever: '从不', + autohide: '自动隐藏' + }, + codeBlast: { + effect: '效果类型', + effectParticles: '粒子效果', + effectExplosion: '爆炸效果', + shake: '震动效果', + maxParticles: '最大粒子数', + shakeIntensity: '震动强度' + }, + codeBlock: { + showBackground: '显示背景', + enableAutoDetection: '启用自动检测' + } + } + }, + extensions: { + rainbowBrackets: { + name: '彩虹括号', + description: '用不同颜色显示嵌套括号' + }, + hyperlink: { + name: '超链接', + description: '识别并可点击超链接' + }, + colorSelector: { + name: '颜色选择器', + description: '颜色值的可视化和选择' + }, + minimap: { + name: '小地图', + description: '显示小地图视图' + }, + codeBlast: { + name: '爆炸效果', + description: '编写时的动画效果' + }, + search: { + name: '搜索功能', + description: '文本搜索和替换功能' + }, + codeBlock: { + name: '代码块', + description: '代码块语法高亮和格式化' + }, + fold: { + name: '代码折叠', + description: '折叠和展开代码段以提高代码可读性' + }, + textHighlight: { + name: '文本高亮', + description: '高亮显示文本选择和搜索匹配项' + } } }; \ No newline at end of file diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index 5aaed39..3103773 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -6,6 +6,7 @@ import EditingPage from '@/views/settings/pages/EditingPage.vue'; import AppearancePage from '@/views/settings/pages/AppearancePage.vue'; import KeyBindingsPage from '@/views/settings/pages/KeyBindingsPage.vue'; import UpdatesPage from '@/views/settings/pages/UpdatesPage.vue'; +import ExtensionsPage from '@/views/settings/pages/ExtensionsPage.vue'; const routes: RouteRecordRaw[] = [ { @@ -34,6 +35,11 @@ const routes: RouteRecordRaw[] = [ name: 'SettingsAppearance', component: AppearancePage }, + { + path: 'extensions', + name: 'SettingsExtensions', + component: ExtensionsPage + }, { path: 'key-bindings', name: 'SettingsKeyBindings', diff --git a/frontend/src/stores/editorStore.ts b/frontend/src/stores/editorStore.ts index 352b3f3..b13222c 100644 --- a/frontend/src/stores/editorStore.ts +++ b/frontend/src/stores/editorStore.ts @@ -6,7 +6,7 @@ import {useConfigStore} from './configStore'; import {useDocumentStore} from './documentStore'; import {useThemeStore} from './themeStore'; import {SystemThemeType} from '@/../bindings/voidraft/internal/models/models'; -import {DocumentService} from '@/../bindings/voidraft/internal/services'; +import {DocumentService, ExtensionService} from '@/../bindings/voidraft/internal/services'; import {ensureSyntaxTree} from "@codemirror/language" import {createBasicSetup} from '@/views/editor/basic/basicSetup'; import {createThemeExtension, updateEditorTheme} from '@/views/editor/basic/themeExtension'; @@ -15,9 +15,8 @@ import {createFontExtensionFromBackend, updateFontConfig} from '@/views/editor/b import {createStatsUpdateExtension} from '@/views/editor/basic/statsExtension'; import {createAutoSavePlugin, createSaveShortcutPlugin} from '@/views/editor/basic/autoSaveExtension'; import {createDynamicKeymapExtension} from '@/views/editor/keymap'; -import { createDynamicExtensions, setExtensionManagerView, getExtensionManager } from '@/views/editor/manager'; -import { useExtensionStore } from './extensionStore'; -import { ExtensionService } from '@/../bindings/voidraft/internal/services'; +import {createDynamicExtensions, getExtensionManager, setExtensionManagerView} from '@/views/editor/manager'; +import {useExtensionStore} from './extensionStore'; export interface DocumentStats { lines: number; @@ -57,7 +56,7 @@ export const useEditorStore = defineStore('editor', () => { if (editorView.value && container && editorView.value.dom.parentElement !== container) { container.appendChild(editorView.value.dom); // 重新挂载后立即滚动到底部 - scrollEditorToBottom(); + scrollToBottom(editorView.value as EditorView); } } @@ -90,13 +89,6 @@ export const useEditorStore = defineStore('editor', () => { } }; - // 滚动到底部的公共方法 - const scrollEditorToBottom = () => { - if (editorView.value) { - scrollToBottom(editorView.value as any); - } - }; - // 创建编辑器 const createEditor = async (initialDoc: string = '') => { if (isEditorInitialized.value || !editorContainer.value) return; @@ -152,7 +144,7 @@ export const useEditorStore = defineStore('editor', () => { // 创建动态快捷键扩展 const keymapExtension = await createDynamicKeymapExtension(); - + // 创建动态扩展 const dynamicExtensions = await createDynamicExtensions(); @@ -183,7 +175,7 @@ export const useEditorStore = defineStore('editor', () => { // 将编辑器实例保存到store setEditorView(view); - + // 设置编辑器视图到扩展管理器 setExtensionManagerView(view); @@ -271,17 +263,22 @@ export const useEditorStore = defineStore('editor', () => { // 扩展管理方法 const updateExtension = async (id: any, enabled: boolean, config?: any) => { try { - // 更新后端配置 - await ExtensionService.UpdateExtensionState(id, enabled, config || {}) - + // 如果只是更新启用状态 + if (config === undefined) { + await ExtensionService.UpdateExtensionEnabled(id, enabled) + } else { + // 如果需要更新配置 + await ExtensionService.UpdateExtensionState(id, enabled, config) + } // 更新前端编辑器 const manager = getExtensionManager() - manager.updateExtension(id, enabled, config || {}) - - // 重新加载扩展配置 + if (manager) { + manager.updateExtension(id, enabled, config || {}) + } + await extensionStore.loadExtensions() } catch (error) { - console.error('Failed to update extension:', error) + throw error } } @@ -299,7 +296,6 @@ export const useEditorStore = defineStore('editor', () => { reconfigureFontSettings, handleManualSave, destroyEditor, - scrollEditorToBottom, updateExtension }; }); \ No newline at end of file diff --git a/frontend/src/stores/extensionStore.ts b/frontend/src/stores/extensionStore.ts index d90a7f4..523bda3 100644 --- a/frontend/src/stores/extensionStore.ts +++ b/frontend/src/stores/extensionStore.ts @@ -1,36 +1,17 @@ import { defineStore } from 'pinia' import { computed, ref } from 'vue' -import { Extension, ExtensionID, ExtensionCategory, ExtensionSettings } from '@/../bindings/voidraft/internal/models/models' +import { Extension, ExtensionID } from '@/../bindings/voidraft/internal/models/models' import { ExtensionService } from '@/../bindings/voidraft/internal/services' export const useExtensionStore = defineStore('extension', () => { // 扩展配置数据 const extensions = ref([]) - const settings = ref(null) // 获取启用的扩展 const enabledExtensions = computed(() => extensions.value.filter(ext => ext.enabled) ) - // 根据分类获取扩展 - const getExtensionsByCategory = computed(() => - (category: ExtensionCategory) => - extensions.value.filter(ext => ext.category === category) - ) - - // 获取启用的扩展按分类分组 - const enabledExtensionsByCategory = computed(() => { - const grouped = new Map() - enabledExtensions.value.forEach(ext => { - if (!grouped.has(ext.category)) { - grouped.set(ext.category, []) - } - grouped.get(ext.category)!.push(ext) - }) - return grouped - }) - /** * 从后端加载扩展配置 */ @@ -42,14 +23,6 @@ export const useExtensionStore = defineStore('extension', () => { } } - /** - * 检查扩展是否启用 - */ - const isExtensionEnabled = (id: ExtensionID): boolean => { - const extension = extensions.value.find(ext => ext.id === id) - return extension?.enabled ?? false - } - /** * 获取扩展配置 */ @@ -61,16 +34,10 @@ export const useExtensionStore = defineStore('extension', () => { return { // 状态 extensions, - settings, enabledExtensions, - // 计算属性 - getExtensionsByCategory, - enabledExtensionsByCategory, - // 方法 loadExtensions, - isExtensionEnabled, getExtensionConfig } }) \ No newline at end of file diff --git a/frontend/src/views/editor/manager/ExtensionManager.ts b/frontend/src/views/editor/manager/ExtensionManager.ts index b227854..0a83dec 100644 --- a/frontend/src/views/editor/manager/ExtensionManager.ts +++ b/frontend/src/views/editor/manager/ExtensionManager.ts @@ -1,6 +1,6 @@ -import { Compartment, Extension, StateEffect } from '@codemirror/state' -import { EditorView } from '@codemirror/view' -import { ExtensionID, Extension as ExtensionConfig } from '@/../bindings/voidraft/internal/models/models' +import {Compartment, Extension, StateEffect} from '@codemirror/state' +import {EditorView} from '@codemirror/view' +import {Extension as ExtensionConfig, ExtensionID} from '@/../bindings/voidraft/internal/models/models' /** * 扩展工厂接口 @@ -90,24 +90,22 @@ export class ExtensionManager { for (const config of extensionConfigs) { const compartmentInfo = this.compartments.get(config.id) if (!compartmentInfo) { - console.warn(`Extension ${config.id} is not registered`) continue } // 验证配置 - if (compartmentInfo.factory.validateConfig && + if (compartmentInfo.factory.validateConfig && !compartmentInfo.factory.validateConfig(config.config)) { - console.warn(`Invalid config for extension ${config.id}`) continue } try { - const extension = config.enabled + const extension = config.enabled ? compartmentInfo.factory.create(config.config) : [] // 空扩展表示禁用 extensions.push(compartmentInfo.compartment.of(extension)) - + // 更新状态 compartmentInfo.currentConfig = config.config compartmentInfo.enabled = config.enabled @@ -134,26 +132,24 @@ export class ExtensionManager { * @param config 扩展配置 */ updateExtension(id: ExtensionID, enabled: boolean, config: any = {}): void { + if (!this.view) { - console.warn('Editor view not set') return } const compartmentInfo = this.compartments.get(id) if (!compartmentInfo) { - console.warn(`Extension ${id} is not registered`) return } try { // 验证配置 - if (compartmentInfo.factory.validateConfig && + if (compartmentInfo.factory.validateConfig && !compartmentInfo.factory.validateConfig(config)) { - console.warn(`Invalid config for extension ${id}`) return } - const extension = enabled + const extension = enabled ? compartmentInfo.factory.create(config) : [] @@ -164,8 +160,9 @@ export class ExtensionManager { // 更新状态 compartmentInfo.currentConfig = config compartmentInfo.enabled = enabled + } catch (error) { - console.error(`Failed to update extension ${id}:`, error) + console.error(`[ExtensionManager] Failed to update extension ${id}:`, error) } } @@ -188,19 +185,17 @@ export class ExtensionManager { for (const update of updates) { const compartmentInfo = this.compartments.get(update.id) if (!compartmentInfo) { - console.warn(`Extension ${update.id} is not registered`) continue } try { // 验证配置 - if (compartmentInfo.factory.validateConfig && + if (compartmentInfo.factory.validateConfig && !compartmentInfo.factory.validateConfig(update.config)) { - console.warn(`Invalid config for extension ${update.id}`) continue } - const extension = update.enabled + const extension = update.enabled ? compartmentInfo.factory.create(update.config) : [] @@ -215,7 +210,7 @@ export class ExtensionManager { } if (effects.length > 0) { - this.view.dispatch({ effects }) + this.view.dispatch({effects}) } } @@ -245,7 +240,6 @@ export class ExtensionManager { resetExtensionToDefault(id: ExtensionID): void { const compartmentInfo = this.compartments.get(id) if (!compartmentInfo) { - console.warn(`Extension ${id} is not registered`) return } diff --git a/frontend/src/views/editor/manager/factories.ts b/frontend/src/views/editor/manager/factories.ts index e281472..ca54f98 100644 --- a/frontend/src/views/editor/manager/factories.ts +++ b/frontend/src/views/editor/manager/factories.ts @@ -1,5 +1,6 @@ import {ExtensionFactory, ExtensionManager} from './ExtensionManager' import {ExtensionID} from '@/../bindings/voidraft/internal/models/models' +import i18n from '@/i18n' // 导入现有扩展的创建函数 import rainbowBracketsExtension from '../extensions/rainbowBracket/rainbowBracketsExtension' @@ -192,52 +193,52 @@ const EXTENSION_CONFIGS = { // 编辑增强扩展 [ExtensionID.ExtensionRainbowBrackets]: { factory: rainbowBracketsFactory, - displayName: '彩虹括号', - description: '用不同颜色显示嵌套括号' + displayNameKey: 'extensions.rainbowBrackets.name', + descriptionKey: 'extensions.rainbowBrackets.description' }, [ExtensionID.ExtensionHyperlink]: { factory: hyperlinkFactory, - displayName: '超链接', - description: '识别并可点击超链接' + displayNameKey: 'extensions.hyperlink.name', + descriptionKey: 'extensions.hyperlink.description' }, [ExtensionID.ExtensionColorSelector]: { factory: colorSelectorFactory, - displayName: '颜色选择器', - description: '颜色值的可视化和选择' + displayNameKey: 'extensions.colorSelector.name', + descriptionKey: 'extensions.colorSelector.description' }, // UI增强扩展 [ExtensionID.ExtensionMinimap]: { factory: minimapFactory, - displayName: '小地图', - description: '显示小地图视图' + displayNameKey: 'extensions.minimap.name', + descriptionKey: 'extensions.minimap.description' }, [ExtensionID.ExtensionCodeBlast]: { factory: codeBlastFactory, - displayName: '爆炸效果', - description: '编写时的动画效果' + displayNameKey: 'extensions.codeBlast.name', + descriptionKey: 'extensions.codeBlast.description' }, // 工具扩展 [ExtensionID.ExtensionSearch]: { factory: searchFactory, - displayName: '搜索功能', - description: '文本搜索和替换功能' + displayNameKey: 'extensions.search.name', + descriptionKey: 'extensions.search.description' }, [ExtensionID.ExtensionCodeBlock]: { factory: codeBlockFactory, - displayName: '代码块', - description: '代码块语法高亮和格式化' + displayNameKey: 'extensions.codeBlock.name', + descriptionKey: 'extensions.codeBlock.description' }, [ExtensionID.ExtensionFold]: { factory: foldFactory, - displayName: '折叠', - description: '折叠' + displayNameKey: 'extensions.fold.name', + descriptionKey: 'extensions.fold.description' }, - [ExtensionID.ExtensionTextHighlight]:{ + [ExtensionID.ExtensionTextHighlight]: { factory: textHighlightFactory, - displayName: '文本高亮', - description: '文本高亮' + displayNameKey: 'extensions.textHighlight.name', + descriptionKey: 'extensions.textHighlight.description' } } @@ -257,8 +258,8 @@ export function registerAllExtensions(manager: ExtensionManager): void { * @returns 显示名称 */ export function getExtensionDisplayName(id: ExtensionID): string { - if (id === ExtensionID.$zero) return '' - return EXTENSION_CONFIGS[id as Exclude]?.displayName || id + const config = EXTENSION_CONFIGS[id as ExtensionID] + return config?.displayNameKey ? i18n.global.t(config.displayNameKey) : id } /** @@ -267,24 +268,8 @@ export function getExtensionDisplayName(id: ExtensionID): string { * @returns 描述 */ export function getExtensionDescription(id: ExtensionID): string { - if (id === ExtensionID.$zero) return '' - return EXTENSION_CONFIGS[id as Exclude]?.description || '未知扩展' -} - -/** - * 获取扩展的完整信息 - * @param id 扩展ID - * @returns 扩展信息对象 - */ -export function getExtensionInfo(id: ExtensionID): { displayName: string; description: string } | null { - if (id === ExtensionID.$zero) return null - const config = EXTENSION_CONFIGS[id as Exclude] - if (!config) return null - - return { - displayName: config.displayName, - description: config.description - } + const config = EXTENSION_CONFIGS[id as ExtensionID] + return config?.descriptionKey ? i18n.global.t(config.descriptionKey) : '' } /** diff --git a/frontend/src/views/settings/Settings.vue b/frontend/src/views/settings/Settings.vue index 7223386..382c60f 100644 --- a/frontend/src/views/settings/Settings.vue +++ b/frontend/src/views/settings/Settings.vue @@ -13,6 +13,7 @@ const navItems = [ { id: 'general', icon: '⚙️', route: '/settings/general' }, { id: 'editing', icon: '✏️', route: '/settings/editing' }, { id: 'appearance', icon: '🎨', route: '/settings/appearance' }, + { id: 'extensions', icon: '🧩', route: '/settings/extensions' }, { id: 'keyBindings', icon: '⌨️', route: '/settings/key-bindings' }, { id: 'updates', icon: '🔄', route: '/settings/updates' } ]; diff --git a/frontend/src/views/settings/pages/ExtensionsPage.vue b/frontend/src/views/settings/pages/ExtensionsPage.vue new file mode 100644 index 0000000..504de2c --- /dev/null +++ b/frontend/src/views/settings/pages/ExtensionsPage.vue @@ -0,0 +1,107 @@ + + + + + \ No newline at end of file diff --git a/internal/models/extensions.go b/internal/models/extensions.go index c0c1d9b..455fd06 100644 --- a/internal/models/extensions.go +++ b/internal/models/extensions.go @@ -182,28 +182,6 @@ func (es *ExtensionSettings) GetExtensionByID(id ExtensionID) *Extension { return nil } -// GetEnabledExtensions 获取所有启用的扩展 -func (es *ExtensionSettings) GetEnabledExtensions() []Extension { - var enabled []Extension - for _, ext := range es.Extensions { - if ext.Enabled { - enabled = append(enabled, ext) - } - } - return enabled -} - -// GetExtensionsByCategory 根据分类获取扩展 -func (es *ExtensionSettings) GetExtensionsByCategory(category ExtensionCategory) []Extension { - var extensions []Extension - for _, ext := range es.Extensions { - if ext.Category == category { - extensions = append(extensions, ext) - } - } - return extensions -} - // UpdateExtension 更新扩展配置 func (es *ExtensionSettings) UpdateExtension(id ExtensionID, enabled bool, config ExtensionConfig) bool { for i := range es.Extensions { diff --git a/internal/services/extension_service.go b/internal/services/extension_service.go index 47ea367..b9ae944 100644 --- a/internal/services/extension_service.go +++ b/internal/services/extension_service.go @@ -178,8 +178,8 @@ func (es *ExtensionService) saveExtensionConfig() error { return nil } -// GetExtensionSettings 获取完整扩展配置 -func (es *ExtensionService) GetExtensionSettings() (*models.ExtensionSettings, error) { +// GetAllExtensions 获取所有扩展配置 +func (es *ExtensionService) GetAllExtensions() ([]models.Extension, error) { es.mu.RLock() defer es.mu.RUnlock() @@ -187,26 +187,12 @@ func (es *ExtensionService) GetExtensionSettings() (*models.ExtensionSettings, e if err := es.koanf.Unmarshal("", &settings); err != nil { return nil, &ExtensionError{"unmarshal_config", "", err} } - return &settings, nil -} - -// GetAllExtensions 获取所有扩展配置 -func (es *ExtensionService) GetAllExtensions() ([]models.Extension, error) { - settings, err := es.GetExtensionSettings() - if err != nil { - return nil, err - } return settings.Extensions, nil } -// EnableExtension 启用扩展 -func (es *ExtensionService) EnableExtension(id models.ExtensionID) error { - return es.UpdateExtensionState(id, true, nil) -} - -// DisableExtension 禁用扩展 -func (es *ExtensionService) DisableExtension(id models.ExtensionID) error { - return es.UpdateExtensionState(id, false, nil) +// UpdateExtensionEnabled 更新扩展启用状态 +func (es *ExtensionService) UpdateExtensionEnabled(id models.ExtensionID, enabled bool) error { + return es.UpdateExtensionState(id, enabled, nil) } // UpdateExtensionState 更新扩展状态