refactor: extract getLangIcon and editor components to improve structure
This commit is contained in:
@@ -0,0 +1,38 @@
|
|||||||
|
export function getLangIcon(plugin: string | undefined | null) {
|
||||||
|
const name = plugin?.toLowerCase().trim() || ''
|
||||||
|
const mapping: Record<string, string> = {
|
||||||
|
'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 ''
|
||||||
|
}
|
||||||
@@ -7,14 +7,14 @@ import XTerminal from '@/components/XTerminal.vue'
|
|||||||
import { Save, Play, FilePen, TextCursorInput, Eye, X, Download, Trash2 } from 'lucide-vue-next'
|
import { Save, Play, FilePen, TextCursorInput, Eye, X, Download, Trash2 } from 'lucide-vue-next'
|
||||||
import { api, type FileNode, type MiseLanguage } from '@/api'
|
import { api, type FileNode, type MiseLanguage } from '@/api'
|
||||||
import { toast } from 'vue-sonner'
|
import { toast } from 'vue-sonner'
|
||||||
import { PATHS, FILE_RUNNERS } from '@/constants'
|
import { PATHS } from '@/constants'
|
||||||
|
|
||||||
// New component imports
|
// New component imports
|
||||||
import FileSidebar from './components/FileSidebar.vue'
|
import FileSidebar from './components/FileSidebar.vue'
|
||||||
import RunConfigDialog from './components/RunConfigDialog.vue'
|
import RunConfigDialog from './components/RunConfigDialog.vue'
|
||||||
import FileActionDialogs from './components/FileActionDialogs.vue'
|
import FileActionDialogs from './components/FileActionDialogs.vue'
|
||||||
import BaihuDialog from '@/components/ui/BaihuDialog.vue'
|
import UnsavedConfirmDialog from './components/UnsavedConfirmDialog.vue'
|
||||||
import { AlertCircle } from 'lucide-vue-next'
|
import { buildExecutionCommand } from './utils'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -73,41 +73,7 @@ async function fetchInstalledLangs() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLangIcon(plugin: string) {
|
import { getLangIcon } from '@/utils/icons'
|
||||||
const name = plugin.toLowerCase().trim()
|
|
||||||
const mapping: Record<string, string> = {
|
|
||||||
'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]}` : ''
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchPaths() {
|
async function fetchPaths() {
|
||||||
try {
|
try {
|
||||||
@@ -370,27 +336,10 @@ async function runScript() {
|
|||||||
|
|
||||||
async function startExecution() {
|
async function startExecution() {
|
||||||
if (!selectedFile.value) return
|
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
|
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
|
showRunDialog.value = false
|
||||||
showTerminalDialog.value = true
|
showTerminalDialog.value = true
|
||||||
await nextTick()
|
await nextTick()
|
||||||
@@ -557,27 +506,10 @@ onUnmounted(() => {
|
|||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
<BaihuDialog v-model:open="confirmLeave.show" title="未保存的更改" icon="AlertCircle" size="sm">
|
<UnsavedConfirmDialog
|
||||||
<div class="flex flex-col sm:flex-row items-center sm:items-start gap-4 p-1">
|
v-model:open="confirmLeave.show"
|
||||||
<div class="h-12 w-12 rounded-full bg-yellow-500/10 flex items-center justify-center shrink-0">
|
:path="confirmLeave.path"
|
||||||
<AlertCircle class="h-6 w-6 text-yellow-500" />
|
@confirm="confirmLeave.onConfirm()"
|
||||||
</div>
|
/>
|
||||||
<div class="flex-1 text-center sm:text-left">
|
|
||||||
<p class="text-sm text-foreground/90 leading-relaxed font-medium">文件尚未保存</p>
|
|
||||||
<p class="text-[13px] text-muted-foreground mt-1">
|
|
||||||
当前文件有未保存的更改。如果现在离开,您的更改将会丢失。
|
|
||||||
</p>
|
|
||||||
<div class="mt-3 px-2 py-1.5 bg-muted/50 rounded text-[11px] font-mono text-muted-foreground break-all border border-muted">
|
|
||||||
{{ confirmLeave.path }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<template #footer>
|
|
||||||
<div class="flex flex-col-reverse sm:flex-row gap-2 w-full sm:w-auto mt-2 sm:mt-0">
|
|
||||||
<Button variant="outline" @click="confirmLeave.show = false" class="w-full sm:w-24">继续编辑</Button>
|
|
||||||
<Button variant="destructive" @click="confirmLeave.show = false; confirmLeave.onConfirm()" class="w-full sm:w-auto px-6">放弃更改</Button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</BaihuDialog>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
|
import BaihuDialog from '@/components/ui/BaihuDialog.vue'
|
||||||
|
import { AlertCircle } from 'lucide-vue-next'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
open: boolean
|
||||||
|
path: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
'update:open': [value: boolean]
|
||||||
|
'confirm': []
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<BaihuDialog :open="open" @update:open="emit('update:open', $event)" title="未保存的更改" icon="AlertCircle" size="sm">
|
||||||
|
<div class="flex flex-col sm:flex-row items-center sm:items-start gap-4 p-1">
|
||||||
|
<div class="h-12 w-12 rounded-full bg-yellow-500/10 flex items-center justify-center shrink-0">
|
||||||
|
<AlertCircle class="h-6 w-6 text-yellow-500" />
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 text-center sm:text-left">
|
||||||
|
<p class="text-sm text-foreground/90 leading-relaxed font-medium">文件尚未保存</p>
|
||||||
|
<p class="text-[13px] text-muted-foreground mt-1">
|
||||||
|
当前文件有未保存的更改。如果现在离开,您的更改将会丢失。
|
||||||
|
</p>
|
||||||
|
<div class="mt-3 px-2 py-1.5 bg-muted/50 rounded text-[11px] font-mono text-muted-foreground break-all border border-muted">
|
||||||
|
{{ path }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<div class="flex flex-col-reverse sm:flex-row gap-2 w-full sm:w-auto mt-2 sm:mt-0">
|
||||||
|
<Button variant="outline" @click="emit('update:open', false)" class="w-full sm:w-24">继续编辑</Button>
|
||||||
|
<Button variant="destructive" @click="emit('update:open', false); emit('confirm')" class="w-full sm:w-auto px-6">放弃更改</Button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</BaihuDialog>
|
||||||
|
</template>
|
||||||
@@ -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}`
|
||||||
|
}
|
||||||
@@ -267,45 +267,7 @@ async function handleTerminalClose() {
|
|||||||
await loadLanguages()
|
await loadLanguages()
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLangIcon(plugin: string) {
|
import { getLangIcon } from '@/utils/icons'
|
||||||
const name = plugin.toLowerCase().trim()
|
|
||||||
const mapping: Record<string, string> = {
|
|
||||||
'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 ''
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleVerify(lang: MiseLanguage) {
|
async function handleVerify(lang: MiseLanguage) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -124,46 +124,7 @@ async function fetchInstalledLangs() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLangIcon(plugin: string) {
|
import { getLangIcon } from '@/utils/icons'
|
||||||
const name = plugin?.toLowerCase().trim()
|
|
||||||
const mapping: Record<string, string> = {
|
|
||||||
'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 ''
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateAvailableVersions(lang: { name: string; version: string; availableVersions: string[] }) {
|
function updateAvailableVersions(lang: { name: string; version: string; availableVersions: string[] }) {
|
||||||
if (lang.name) {
|
if (lang.name) {
|
||||||
lang.availableVersions = installedLangs.value
|
lang.availableVersions = installedLangs.value
|
||||||
|
|||||||
@@ -165,45 +165,7 @@ async function fetchInstalledLangs() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLangIcon(plugin: string) {
|
import { getLangIcon } from '@/utils/icons'
|
||||||
const name = plugin?.toLowerCase().trim()
|
|
||||||
const mapping: Record<string, string> = {
|
|
||||||
'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 ''
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateAvailableVersions(lang: { name: string; version: string; availableVersions: string[] }) {
|
function updateAvailableVersions(lang: { name: string; version: string; availableVersions: string[] }) {
|
||||||
if (lang.name) {
|
if (lang.name) {
|
||||||
|
|||||||
Reference in New Issue
Block a user