-
+
@@ -119,27 +128,99 @@
diff --git a/src/composables/useCodeMirrorEditor.ts b/src/composables/useCodeMirrorEditor.ts
index 6e645912..00b1558e 100644
--- a/src/composables/useCodeMirrorEditor.ts
+++ b/src/composables/useCodeMirrorEditor.ts
@@ -2,6 +2,7 @@ import { nextTick, ref, watch } from 'vue'
import { python } from '@codemirror/lang-python'
import { javascript } from '@codemirror/lang-javascript'
import { go } from '@codemirror/lang-go'
+import { java } from '@codemirror/lang-java'
import {
abcdef,
abyss,
@@ -66,12 +67,7 @@ interface Props
language?: string
}
-interface Emit
-{
- (event: 'update:modelValue', value: string): void
-}
-
-export function useCodeMirrorEditor(props: Props, _emit: Emit)
+export function useCodeMirrorEditor(props: Props)
{
const toast = useToast()
@@ -155,6 +151,8 @@ export function useCodeMirrorEditor(props: Props, _emit: Emit)
return javascript()
case 'go':
return go()
+ case 'java':
+ return java()
default:
return null
}
diff --git a/src/composables/useEventManager.ts b/src/composables/useEventManager.ts
index 22f2c80b..edddc2b4 100644
--- a/src/composables/useEventManager.ts
+++ b/src/composables/useEventManager.ts
@@ -1,5 +1,4 @@
import type { Ref } from 'vue'
-import { ref } from 'vue'
import { listen, UnlistenFn } from '@tauri-apps/api/event'
import { CodeOutputEvent } from '../types/app.ts'
@@ -14,6 +13,11 @@ interface EventManagerOptions
lastExecutionTime: Ref
currentLanguage: Ref
toast: any
+ handleRealtimeOutput: (currentLanguage: string, data: any) => void
+ handleExecutionComplete: (currentLanguage: string, data: any) => void
+ handleExecutionStopped: (currentLanguage: string, data: any) => void
+ handleExecutionTimeout: (currentLanguage: string, data: any) => void
+ handleExecutionError: (currentLanguage: string, data: any) => void
}
export function useEventManager(options: EventManagerOptions)
@@ -22,12 +26,12 @@ export function useEventManager(options: EventManagerOptions)
showAbout,
showSettings,
showUpdate,
- output,
- isRunning,
- isSuccess,
- lastExecutionTime,
currentLanguage,
- toast
+ handleRealtimeOutput,
+ handleExecutionComplete,
+ handleExecutionStopped,
+ handleExecutionTimeout,
+ handleExecutionError
} = options
// 事件监听器引用
@@ -41,40 +45,11 @@ export function useEventManager(options: EventManagerOptions)
let unlistenExecutionTimeoutFn: UnlistenFn | null = null
let unlistenExecutionErrorFn: UnlistenFn | null = null
- // 实时输出相关
- const realTimeOutput = ref('')
- const realTimeStderr = ref('')
-
// 处理实时输出
- const handleRealtimeOutput = (event: any) => {
+ const handleRealtimeOutputWrapper = (event: any) => {
const data: CodeOutputEvent = event.payload
console.log('实时输出:', data)
-
- // 只处理当前语言的输出
- if (data.language !== currentLanguage.value) {
- return
- }
-
- if (data.type === 'stdout') {
- realTimeOutput.value += data.content + '\n'
- }
- else if (data.type === 'stderr') {
- realTimeStderr.value += data.content + '\n'
- }
-
- // 合并输出显示
- let combinedOutput = ''
- if (realTimeOutput.value) {
- combinedOutput += realTimeOutput.value
- }
- if (realTimeStderr.value) {
- if (combinedOutput) {
- combinedOutput += '\n'
- }
- combinedOutput += realTimeStderr.value
- }
-
- output.value = combinedOutput
+ handleRealtimeOutput(currentLanguage.value, data)
}
// 处理执行状态事件
@@ -85,44 +60,26 @@ export function useEventManager(options: EventManagerOptions)
}
}
- const handleExecutionComplete = (event: any) => {
+ const handleExecutionCompleteWrapper = (event: any) => {
const data = event.payload
- if (data.language === currentLanguage.value) {
- isRunning.value = false
- isSuccess.value = data.success
- if (data.execution_time) {
- lastExecutionTime.value = data.execution_time
- }
- console.log('代码执行完成')
- }
+ console.log('代码执行完成')
+ handleExecutionComplete(currentLanguage.value, data)
}
- const handleExecutionStopped = (event: any) => {
+ const handleExecutionStoppedWrapper = (event: any) => {
const data = event.payload
- if (data.language === currentLanguage.value) {
- isRunning.value = false
- output.value += '\n\n🛑 代码执行已被用户停止'
- toast.warning('代码执行已停止')
- console.log('代码执行已停止')
- }
+ console.log('代码执行已停止')
+ handleExecutionStopped(currentLanguage.value, data)
}
- const handleExecutionTimeout = (event: any) => {
+ const handleExecutionTimeoutWrapper = (event: any) => {
const data = event.payload
- if (data.language === currentLanguage.value) {
- isRunning.value = false
- output.value += '\n\n⚠️ 代码执行超时(30秒)'
- toast.error('代码执行超时')
- }
+ handleExecutionTimeout(currentLanguage.value, data)
}
- const handleExecutionError = (event: any) => {
+ const handleExecutionErrorWrapper = (event: any) => {
const data = event.payload
- if (data.language === currentLanguage.value) {
- isRunning.value = false
- output.value += `\n\n❌ 执行错误: ${ data.error }`
- toast.error('代码执行出错')
- }
+ handleExecutionError(currentLanguage.value, data)
}
const initializeEventListeners = async () => {
@@ -140,14 +97,14 @@ export function useEventManager(options: EventManagerOptions)
})
// 监听实时输出事件
- unlistenOutputFn = await listen('code-output', handleRealtimeOutput)
+ unlistenOutputFn = await listen('code-output', handleRealtimeOutputWrapper)
// 监听执行状态事件
unlistenExecutionStartFn = await listen('code-execution-start', handleExecutionStart)
- unlistenExecutionCompleteFn = await listen('code-execution-complete', handleExecutionComplete)
- unlistenExecutionStoppedFn = await listen('code-execution-stopped', handleExecutionStopped)
- unlistenExecutionTimeoutFn = await listen('code-execution-timeout', handleExecutionTimeout)
- unlistenExecutionErrorFn = await listen('code-execution-error', handleExecutionError)
+ unlistenExecutionCompleteFn = await listen('code-execution-complete', handleExecutionCompleteWrapper)
+ unlistenExecutionStoppedFn = await listen('code-execution-stopped', handleExecutionStoppedWrapper)
+ unlistenExecutionTimeoutFn = await listen('code-execution-timeout', handleExecutionTimeoutWrapper)
+ unlistenExecutionErrorFn = await listen('code-execution-error', handleExecutionErrorWrapper)
}
const cleanupEventListeners = () => {
diff --git a/src/composables/usePluginConfig.ts b/src/composables/usePluginConfig.ts
new file mode 100644
index 00000000..253135f8
--- /dev/null
+++ b/src/composables/usePluginConfig.ts
@@ -0,0 +1,280 @@
+import { ref, watch } from 'vue'
+import { invoke } from '@tauri-apps/api/core'
+import { debounce } from 'lodash-es'
+import { open as openDialog } from '@tauri-apps/plugin-dialog'
+import { useToast } from '../plugins/toast'
+import type PluginConfig from '../types/plugin'
+
+interface Language
+{
+ name: string
+ value: string
+}
+
+interface TabData
+{
+ key: string
+ label: string
+ svgUrl?: string
+}
+
+export function usePluginConfig(emit?: any)
+{
+ const toast = useToast()
+
+ // 状态管理
+ const activePlugin = ref('')
+ const activeTab = ref('general')
+ const tabsPluginData = ref([])
+ const globalConfig = ref(null)
+
+ const pluginConfig = ref({
+ enabled: false,
+ execute_home: '',
+ extension: '',
+ language: '',
+ before_compile: '',
+ after_compile: '',
+ run_command: '',
+ template: '',
+ timeout: 30
+ })
+
+ // 获取支持的语言列表
+ const getSupportedLanguages = async () => {
+ try {
+ const languages = await invoke('get_supported_languages')
+ tabsPluginData.value = languages.map((language) => ({
+ key: language.value,
+ label: language.name,
+ svgUrl: `/icons/${ language.value.replace(/\d+$/, '') }.svg`
+ }))
+
+ // 设置默认选中的插件
+ if (tabsPluginData.value.length > 0 && !activePlugin.value) {
+ activePlugin.value = tabsPluginData.value[0].key
+ }
+
+ console.log('支持的语言列表:', tabsPluginData.value)
+ }
+ catch (error) {
+ console.error('获取支持的语言失败:', error)
+ toast.error('获取支持的语言失败 - 错误信息: ' + error)
+ tabsPluginData.value = []
+ }
+ }
+
+ // 获取全局配置
+ const getGlobalConfig = async () => {
+ try {
+ globalConfig.value = await invoke('get_app_config')
+ console.log('全局配置加载成功:', globalConfig.value)
+
+ // 配置加载后处理当前插件配置
+ handleTabChange()
+ }
+ catch (error) {
+ console.error('获取配置失败:', error)
+ toast.error('获取配置失败 - 错误信息: ' + error)
+ }
+ }
+
+ // 处理标签页切换
+ const handleTabChange = () => {
+ if (globalConfig.value && globalConfig.value.plugins && activePlugin.value) {
+ const foundPlugin = globalConfig.value.plugins.find(
+ (plugin: any) => plugin.language === activePlugin.value
+ )
+
+ if (foundPlugin) {
+ pluginConfig.value = { ...foundPlugin }
+ console.log('切换到插件配置:', activePlugin.value, foundPlugin)
+ }
+ else {
+ console.warn('未找到插件配置:', activePlugin.value)
+ // 创建默认配置
+ pluginConfig.value = {
+ enabled: false,
+ execute_home: '',
+ extension: '',
+ language: activePlugin.value,
+ before_compile: '',
+ after_compile: '',
+ run_command: '',
+ template: '',
+ timeout: 30
+ }
+ }
+ }
+ }
+
+ // 选择执行环境目录
+ const selectExecuteHome = async () => {
+ try {
+ const selected = await openDialog({
+ directory: true,
+ multiple: false,
+ title: '选择语言环境目录'
+ })
+
+ if (selected) {
+ pluginConfig.value.execute_home = selected as string
+ console.log('选择的执行环境目录:', selected)
+ }
+ }
+ catch (error) {
+ console.error('选择目录失败:', error)
+ if (emit) {
+ emit('error', '选择目录失败')
+ }
+ }
+ }
+
+ // 更新全局配置
+ const updateGlobalConfig = async (updatedPlugin: PluginConfig) => {
+ if (!globalConfig.value || !globalConfig.value.plugins) {
+ console.error('全局配置未加载或插件列表为空')
+ return
+ }
+
+ try {
+ const pluginIndex = globalConfig.value.plugins.findIndex(
+ (plugin: any) => plugin.language === updatedPlugin.language
+ )
+
+ if (pluginIndex !== -1) {
+ // 更新现有插件配置
+ globalConfig.value.plugins[pluginIndex] = { ...updatedPlugin }
+ }
+ else {
+ // 添加新的插件配置
+ globalConfig.value.plugins.push({ ...updatedPlugin })
+ }
+
+ await invoke('update_app_config', { config: globalConfig.value })
+
+ const pluginLabel = tabsPluginData.value.find(
+ (tab: any) => tab.key === updatedPlugin.language
+ )?.label || updatedPlugin.language
+
+ toast.success(`${ pluginLabel } 配置已保存`)
+
+ if (emit) {
+ emit('settings-changed', updatedPlugin)
+ }
+
+ console.log('插件配置保存成功:', updatedPlugin)
+ }
+ catch (error) {
+ console.error('保存配置失败:', error)
+ toast.error('保存配置失败 - 错误信息: ' + error)
+
+ if (emit) {
+ emit('error', '保存配置失败')
+ }
+ }
+ }
+
+ // 防抖更新
+ const debouncedUpdate = debounce((config: PluginConfig) => {
+ updateGlobalConfig(config)
+ }, 1000)
+
+ // 手动保存配置
+ const saveConfig = async () => {
+ if (pluginConfig.value.language) {
+ await updateGlobalConfig(pluginConfig.value)
+ }
+ }
+
+ // 重置插件配置
+ const resetPluginConfig = (language: string) => {
+ pluginConfig.value = {
+ enabled: false,
+ execute_home: '',
+ extension: '',
+ language: language,
+ before_compile: '',
+ after_compile: '',
+ run_command: '',
+ template: '',
+ timeout: 30
+ }
+ }
+
+ // 获取插件配置
+ const getPluginConfig = (language: string) => {
+ if (globalConfig.value && globalConfig.value.plugins) {
+ return globalConfig.value.plugins.find(
+ (plugin: any) => plugin.language === language
+ )
+ }
+ return null
+ }
+
+ // 验证插件配置
+ const validatePluginConfig = (config: PluginConfig): boolean => {
+ if (!config.language) {
+ toast.error('语言不能为空')
+ return false
+ }
+
+ if (!config.run_command) {
+ toast.error('执行命令不能为空')
+ return false
+ }
+
+ if (config.timeout && (config.timeout < 1 || config.timeout > 300)) {
+ toast.error('超时时间必须在 1-300 秒之间')
+ return false
+ }
+
+ return true
+ }
+
+ // 初始化插件管理器
+ const initializePlugin = async () => {
+ await getSupportedLanguages()
+ await getGlobalConfig()
+ }
+
+ // 监听插件配置变化
+ watch(pluginConfig, (newConfig, oldConfig) => {
+ if (oldConfig && newConfig.language) {
+ console.log('插件配置变化:', oldConfig, '->', newConfig)
+ debouncedUpdate(newConfig)
+ }
+ }, {
+ deep: true,
+ flush: 'post'
+ })
+
+ // 监听活动插件变化
+ watch(activePlugin, (newPlugin, oldPlugin) => {
+ if (newPlugin && newPlugin !== oldPlugin) {
+ console.log('切换插件:', oldPlugin, '->', newPlugin)
+ handleTabChange()
+ }
+ })
+
+ return {
+ // 状态
+ activePlugin,
+ activeTab,
+ tabsPluginData,
+ globalConfig,
+ pluginConfig,
+
+ // 方法
+ getSupportedLanguages,
+ getGlobalConfig,
+ handleTabChange,
+ selectExecuteHome,
+ updateGlobalConfig,
+ saveConfig,
+ resetPluginConfig,
+ getPluginConfig,
+ validatePluginConfig,
+ initializePlugin
+ }
+}