ui: open artifact files in new tab instead of inline expand

This commit is contained in:
Fam Zheng
2026-03-09 17:05:20 +00:00
parent f214b67f92
commit 4c68ff36ee

View File

@@ -14,9 +14,6 @@ const emit = defineEmits<{
}>() }>()
const expandedSteps = ref<Set<number>>(new Set()) const expandedSteps = ref<Set<number>>(new Set())
const expandedArtifact = ref<{ stepOrder: number; path: string } | null>(null)
const artifactContent = ref<string>('')
const artifactLoading = ref(false)
function toggleStep(order: number) { function toggleStep(order: number) {
if (expandedSteps.value.has(order)) { if (expandedSteps.value.has(order)) {
@@ -48,31 +45,9 @@ function artifactIcon(type: string) {
} }
} }
async function toggleArtifact(e: Event, stepOrder: number, path: string) { function openArtifact(e: Event, path: string) {
e.stopPropagation() e.stopPropagation()
if (expandedArtifact.value?.stepOrder === stepOrder && expandedArtifact.value?.path === path) { window.open(`${BASE}/projects/${props.projectId}/files/${path}`, '_blank')
expandedArtifact.value = null
return
}
expandedArtifact.value = { stepOrder, path }
artifactLoading.value = true
artifactContent.value = ''
try {
const res = await fetch(`${BASE}/projects/${props.projectId}/files/${path}`)
if (res.ok) {
artifactContent.value = await res.text()
} else {
artifactContent.value = `Error: ${res.status} ${res.statusText}`
}
} catch (err) {
artifactContent.value = `Error: ${err}`
} finally {
artifactLoading.value = false
}
}
function isArtifactExpanded(stepOrder: number, path: string) {
return expandedArtifact.value?.stepOrder === stepOrder && expandedArtifact.value?.path === path
} }
</script> </script>
@@ -105,20 +80,12 @@ function isArtifactExpanded(stepOrder: number, path: string) {
v-for="a in step.artifacts" v-for="a in step.artifacts"
:key="a.path" :key="a.path"
class="artifact-tag" class="artifact-tag"
:class="{ active: isArtifactExpanded(step.order, a.path) }" @click="openArtifact($event, a.path)"
@click="toggleArtifact($event, step.order, a.path)"
:title="a.description || a.path" :title="a.description || a.path"
> >
<span class="artifact-icon">{{ artifactIcon(a.artifact_type) }}</span> <span class="artifact-icon">{{ artifactIcon(a.artifact_type) }}</span>
<span class="artifact-name">{{ a.name }}</span> <span class="artifact-name">{{ a.name }}</span>
</button> </button>
<div
v-if="expandedArtifact && step.artifacts.some(a => isArtifactExpanded(step.order, a.path))"
class="artifact-content"
>
<div v-if="artifactLoading" class="artifact-loading">加载中...</div>
<pre v-else>{{ artifactContent }}</pre>
</div>
</div> </div>
</div> </div>
<div v-if="!steps.length" class="empty-state"> <div v-if="!steps.length" class="empty-state">
@@ -275,12 +242,6 @@ function isArtifactExpanded(stepOrder: number, path: string) {
color: var(--accent); color: var(--accent);
} }
.artifact-tag.active {
border-color: var(--accent);
background: rgba(79, 195, 247, 0.12);
color: var(--accent);
}
.artifact-icon { .artifact-icon {
font-size: 10px; font-size: 10px;
font-weight: 600; font-weight: 600;
@@ -291,35 +252,6 @@ function isArtifactExpanded(stepOrder: number, path: string) {
font-weight: 500; font-weight: 500;
} }
.artifact-content {
width: 100%;
margin-top: 4px;
border-radius: 4px;
background: var(--bg-card);
border: 1px solid var(--border);
overflow: hidden;
}
.artifact-content pre {
margin: 0;
padding: 8px 12px;
font-size: 11px;
line-height: 1.5;
color: var(--text-primary);
overflow-x: auto;
max-height: 400px;
overflow-y: auto;
white-space: pre-wrap;
word-break: break-all;
}
.artifact-loading {
padding: 12px;
text-align: center;
color: var(--text-secondary);
font-size: 12px;
}
.empty-state { .empty-state {
color: var(--text-secondary); color: var(--text-secondary);
font-size: 13px; font-size: 13px;