diff --git a/web/src/utils/icons.ts b/web/src/utils/icons.ts new file mode 100644 index 0000000..2966dd6 --- /dev/null +++ b/web/src/utils/icons.ts @@ -0,0 +1,38 @@ +export function getLangIcon(plugin: string | undefined | null) { + const name = plugin?.toLowerCase().trim() || '' + const mapping: Record = { + 'python': 'python/python-original.svg', + 'node': 'nodejs/nodejs-original.svg', + 'nodejs': 'nodejs/nodejs-original.svg', + 'go': 'go/go-original.svg', + 'rust': 'rust/rust-original.svg', + 'ruby': 'ruby/ruby-plain.svg', + 'php': 'php/php-plain.svg', + 'java': 'java/java-plain.svg', + 'deno': 'deno/deno-plain.svg', + 'bun': 'bun/bun-plain.svg', + 'zig': 'zig/zig-original.svg', + 'dotnet': 'dot-net/dot-net-original.svg', + '.net': 'dot-net/dot-net-original.svg', + 'elixir': 'elixir/elixir-original.svg', + 'erlang': 'erlang/erlang-original.svg', + 'crystal': 'crystal/crystal-original.svg', + 'lua': 'lua/lua-original.svg', + 'julia': 'julia/julia-original.svg', + 'nim': 'nim/nim-original.svg', + 'perl': 'perl/perl-original.svg', + 'scala': 'scala/scala-original.svg', + 'kotlin': 'kotlin/kotlin-original.svg', + 'clojure': 'clojure/clojure-line.svg', + 'dart': 'dart/dart-original.svg', + 'flutter': 'flutter/flutter-original.svg', + 'terraform': 'terraform/terraform-original.svg', + 'docker': 'docker/docker-original.svg', + 'kubernetes': 'kubernetes/kubernetes-plain.svg', + 'ansible': 'ansible/ansible-original.svg', + } + if (mapping[name]) { + return `https://fastly.jsdelivr.net/gh/devicons/devicon/icons/${mapping[name]}` + } + return '' +} diff --git a/web/src/views/editor/Editor.vue b/web/src/views/editor/Editor.vue index 7000b71..922d8c3 100644 --- a/web/src/views/editor/Editor.vue +++ b/web/src/views/editor/Editor.vue @@ -7,14 +7,14 @@ import XTerminal from '@/components/XTerminal.vue' import { Save, Play, FilePen, TextCursorInput, Eye, X, Download, Trash2 } from 'lucide-vue-next' import { api, type FileNode, type MiseLanguage } from '@/api' import { toast } from 'vue-sonner' -import { PATHS, FILE_RUNNERS } from '@/constants' +import { PATHS } from '@/constants' // New component imports import FileSidebar from './components/FileSidebar.vue' import RunConfigDialog from './components/RunConfigDialog.vue' import FileActionDialogs from './components/FileActionDialogs.vue' -import BaihuDialog from '@/components/ui/BaihuDialog.vue' -import { AlertCircle } from 'lucide-vue-next' +import UnsavedConfirmDialog from './components/UnsavedConfirmDialog.vue' +import { buildExecutionCommand } from './utils' const route = useRoute() const router = useRouter() @@ -73,41 +73,7 @@ async function fetchInstalledLangs() { } } -function getLangIcon(plugin: string) { - const name = plugin.toLowerCase().trim() - const mapping: Record = { - 'python': 'python/python-original.svg', - 'node': 'nodejs/nodejs-original.svg', - 'nodejs': 'nodejs/nodejs-original.svg', - 'go': 'go/go-original.svg', - 'rust': 'rust/rust-original.svg', - 'ruby': 'ruby/ruby-plain.svg', - 'php': 'php/php-plain.svg', - 'java': 'java/java-plain.svg', - 'deno': 'deno/deno-plain.svg', - 'bun': 'bun/bun-plain.svg', - 'zig': 'zig/zig-original.svg', - 'dotnet': 'dot-net/dot-net-original.svg', - '.net': 'dot-net/dot-net-original.svg', - 'elixir': 'elixir/elixir-original.svg', - 'erlang': 'erlang/erlang-original.svg', - 'crystal': 'crystal/crystal-original.svg', - 'lua': 'lua/lua-original.svg', - 'julia': 'julia/julia-original.svg', - 'nim': 'nim/nim-original.svg', - 'perl': 'perl/perl-original.svg', - 'scala': 'scala/scala-original.svg', - 'kotlin': 'kotlin/kotlin-original.svg', - 'clojure': 'clojure/clojure-line.svg', - 'dart': 'dart/dart-original.svg', - 'flutter': 'flutter/flutter-original.svg', - 'terraform': 'terraform/terraform-original.svg', - 'docker': 'docker/docker-original.svg', - 'kubernetes': 'kubernetes/kubernetes-plain.svg', - 'ansible': 'ansible/ansible-original.svg', - } - return mapping[name] ? `https://fastly.jsdelivr.net/gh/devicons/devicon/icons/${mapping[name]}` : '' -} +import { getLangIcon } from '@/utils/icons' async function fetchPaths() { try { @@ -370,27 +336,10 @@ async function runScript() { async function startExecution() { if (!selectedFile.value) return - const parts = selectedFile.value.split('/') - const fileName = parts.pop() || selectedFile.value - const dirPath = parts.join('/') - const ext = fileName.split('.').pop()?.toLowerCase() || '' - let runner = FILE_RUNNERS[ext] || '' - - const validEnvs = selectedEnvs.value.filter(e => e.plugin && e.version) - let cmd = '' - if (validEnvs.length > 0) { - const specs = validEnvs.map(e => `${e.plugin}@${e.version}`).join(' ') - if (!runner && !['sh', 'bash'].includes(ext)) { - const first = validEnvs[0]!.plugin - runner = (first === 'node' ? 'node' : first) - } - cmd = `mise exec ${specs} -- ${runner ? `${runner} ${fileName}` : `./${fileName}`}` - } else { - cmd = runner ? `${runner} ${fileName}` : `./${fileName}` - } - + const base = scriptsDir.value || PATHS.SCRIPTS_DIR - runCommand.value = `cd ${base}${dirPath ? '/' + dirPath : ''} && ${cmd}` + runCommand.value = buildExecutionCommand(selectedFile.value, selectedEnvs.value, base) + showRunDialog.value = false showTerminalDialog.value = true await nextTick() @@ -557,27 +506,10 @@ onUnmounted(() => { - -
-
- -
-
-

文件尚未保存

-

- 当前文件有未保存的更改。如果现在离开,您的更改将会丢失。 -

-
- {{ confirmLeave.path }} -
-
-
- -
+ diff --git a/web/src/views/editor/components/UnsavedConfirmDialog.vue b/web/src/views/editor/components/UnsavedConfirmDialog.vue new file mode 100644 index 0000000..50fb21e --- /dev/null +++ b/web/src/views/editor/components/UnsavedConfirmDialog.vue @@ -0,0 +1,40 @@ + + + diff --git a/web/src/views/editor/utils.ts b/web/src/views/editor/utils.ts new file mode 100644 index 0000000..86902b2 --- /dev/null +++ b/web/src/views/editor/utils.ts @@ -0,0 +1,28 @@ +import { FILE_RUNNERS } from '@/constants' + +export function buildExecutionCommand( + selectedFile: string, + selectedEnvs: { plugin: string; version: string }[], + baseDir: string +): string { + const parts = selectedFile.split('/') + const fileName = parts.pop() || selectedFile + const dirPath = parts.join('/') + const ext = fileName.split('.').pop()?.toLowerCase() || '' + let runner = FILE_RUNNERS[ext] || '' + + const validEnvs = selectedEnvs.filter(e => e.plugin && e.version) + let cmd = '' + if (validEnvs.length > 0) { + const specs = validEnvs.map(e => `${e.plugin}@${e.version}`).join(' ') + if (!runner && !['sh', 'bash'].includes(ext)) { + const first = validEnvs[0]!.plugin + runner = (first === 'node' ? 'node' : first) + } + cmd = `mise exec ${specs} -- ${runner ? `${runner} ${fileName}` : `./${fileName}`}` + } else { + cmd = runner ? `${runner} ${fileName}` : `./${fileName}` + } + + return `cd ${baseDir}${dirPath ? '/' + dirPath : ''} && ${cmd}` +} diff --git a/web/src/views/languages/Languages.vue b/web/src/views/languages/Languages.vue index e0894c4..aaed302 100644 --- a/web/src/views/languages/Languages.vue +++ b/web/src/views/languages/Languages.vue @@ -267,45 +267,7 @@ async function handleTerminalClose() { await loadLanguages() } -function getLangIcon(plugin: string) { - const name = plugin.toLowerCase().trim() - const mapping: Record = { - 'python': 'python/python-original.svg', - 'node': 'nodejs/nodejs-original.svg', - 'nodejs': 'nodejs/nodejs-original.svg', - 'go': 'go/go-original.svg', - 'rust': 'rust/rust-original.svg', - 'ruby': 'ruby/ruby-plain.svg', - 'php': 'php/php-plain.svg', - 'java': 'java/java-plain.svg', - 'deno': 'deno/deno-plain.svg', - 'bun': 'bun/bun-plain.svg', - 'zig': 'zig/zig-original.svg', - 'dotnet': 'dot-net/dot-net-original.svg', - '.net': 'dot-net/dot-net-original.svg', - 'elixir': 'elixir/elixir-original.svg', - 'erlang': 'erlang/erlang-original.svg', - 'crystal': 'crystal/crystal-original.svg', - 'lua': 'lua/lua-original.svg', - 'julia': 'julia/julia-original.svg', - 'nim': 'nim/nim-original.svg', - 'perl': 'perl/perl-original.svg', - 'scala': 'scala/scala-original.svg', - 'kotlin': 'kotlin/kotlin-original.svg', - 'clojure': 'clojure/clojure-line.svg', - 'dart': 'dart/dart-original.svg', - 'flutter': 'flutter/flutter-original.svg', - 'terraform': 'terraform/terraform-original.svg', - 'docker': 'docker/docker-original.svg', - 'kubernetes': 'kubernetes/kubernetes-plain.svg', - 'ansible': 'ansible/ansible-original.svg', - } - - if (mapping[name]) { - return `https://fastly.jsdelivr.net/gh/devicons/devicon/icons/${mapping[name]}` - } - return '' -} +import { getLangIcon } from '@/utils/icons' async function handleVerify(lang: MiseLanguage) { try { diff --git a/web/src/views/tasks/RepoDialog.vue b/web/src/views/tasks/RepoDialog.vue index fe65aa5..df897dd 100644 --- a/web/src/views/tasks/RepoDialog.vue +++ b/web/src/views/tasks/RepoDialog.vue @@ -124,46 +124,7 @@ async function fetchInstalledLangs() { } } -function getLangIcon(plugin: string) { - const name = plugin?.toLowerCase().trim() - const mapping: Record = { - 'python': 'python/python-original.svg', - 'node': 'nodejs/nodejs-original.svg', - 'nodejs': 'nodejs/nodejs-original.svg', - 'go': 'go/go-original.svg', - 'rust': 'rust/rust-original.svg', - 'ruby': 'ruby/ruby-plain.svg', - 'php': 'php/php-plain.svg', - 'java': 'java/java-plain.svg', - 'deno': 'deno/deno-plain.svg', - 'bun': 'bun/bun-plain.svg', - 'zig': 'zig/zig-original.svg', - 'dotnet': 'dot-net/dot-net-original.svg', - '.net': 'dot-net/dot-net-original.svg', - 'elixir': 'elixir/elixir-original.svg', - 'erlang': 'erlang/erlang-original.svg', - 'crystal': 'crystal/crystal-original.svg', - 'lua': 'lua/lua-original.svg', - 'julia': 'julia/julia-original.svg', - 'nim': 'nim/nim-original.svg', - 'perl': 'perl/perl-original.svg', - 'scala': 'scala/scala-original.svg', - 'kotlin': 'kotlin/kotlin-original.svg', - 'clojure': 'clojure/clojure-line.svg', - 'dart': 'dart/dart-original.svg', - 'flutter': 'flutter/flutter-original.svg', - 'terraform': 'terraform/terraform-original.svg', - 'docker': 'docker/docker-original.svg', - 'kubernetes': 'kubernetes/kubernetes-plain.svg', - 'ansible': 'ansible/ansible-original.svg', - } - - if (mapping[name]) { - return `https://fastly.jsdelivr.net/gh/devicons/devicon/icons/${mapping[name]}` - } - return '' -} - +import { getLangIcon } from '@/utils/icons' function updateAvailableVersions(lang: { name: string; version: string; availableVersions: string[] }) { if (lang.name) { lang.availableVersions = installedLangs.value diff --git a/web/src/views/tasks/TaskDialog.vue b/web/src/views/tasks/TaskDialog.vue index 3d186b6..e634c29 100644 --- a/web/src/views/tasks/TaskDialog.vue +++ b/web/src/views/tasks/TaskDialog.vue @@ -165,45 +165,7 @@ async function fetchInstalledLangs() { } } -function getLangIcon(plugin: string) { - const name = plugin?.toLowerCase().trim() - const mapping: Record = { - 'python': 'python/python-original.svg', - 'node': 'nodejs/nodejs-original.svg', - 'nodejs': 'nodejs/nodejs-original.svg', - 'go': 'go/go-original.svg', - 'rust': 'rust/rust-original.svg', - 'ruby': 'ruby/ruby-plain.svg', - 'php': 'php/php-plain.svg', - 'java': 'java/java-plain.svg', - 'deno': 'deno/deno-plain.svg', - 'bun': 'bun/bun-plain.svg', - 'zig': 'zig/zig-original.svg', - 'dotnet': 'dot-net/dot-net-original.svg', - '.net': 'dot-net/dot-net-original.svg', - 'elixir': 'elixir/elixir-original.svg', - 'erlang': 'erlang/erlang-original.svg', - 'crystal': 'crystal/crystal-original.svg', - 'lua': 'lua/lua-original.svg', - 'julia': 'julia/julia-original.svg', - 'nim': 'nim/nim-original.svg', - 'perl': 'perl/perl-original.svg', - 'scala': 'scala/scala-original.svg', - 'kotlin': 'kotlin/kotlin-original.svg', - 'clojure': 'clojure/clojure-line.svg', - 'dart': 'dart/dart-original.svg', - 'flutter': 'flutter/flutter-original.svg', - 'terraform': 'terraform/terraform-original.svg', - 'docker': 'docker/docker-original.svg', - 'kubernetes': 'kubernetes/kubernetes-plain.svg', - 'ansible': 'ansible/ansible-original.svg', - } - - if (mapping[name]) { - return `https://fastly.jsdelivr.net/gh/devicons/devicon/icons/${mapping[name]}` - } - return '' -} +import { getLangIcon } from '@/utils/icons' function updateAvailableVersions(lang: { name: string; version: string; availableVersions: string[] }) { if (lang.name) {