simpleasm/frontend/src/components/OutputConsole.vue
Fam Zheng e465b1cf71 Initial commit: Simple ASM - ARM assembly learning game
10-level progressive game teaching ARM assembly basics:
registers, arithmetic, bitwise ops, memory, branching, loops.
Vue 3 + FastAPI + SQLite with K8s deployment.
2026-04-07 10:17:15 +01:00

73 lines
2.2 KiB
Vue

<template>
<div class="output-console">
<div class="console-header">
<span>输出</span>
<button v-if="messages.length" @click="$emit('clear')" class="clear-btn">清除</button>
</div>
<div class="console-body" ref="bodyEl">
<div v-for="(m, i) in messages" :key="i" class="console-line" :class="m.type">
<span class="pfx">{{ m.pfx }}</span>
<span>{{ m.text }}</span>
</div>
<div v-if="!messages.length" class="empty">等待运行...</div>
</div>
</div>
</template>
<script setup>
import { computed, ref, watch, nextTick } from 'vue'
const props = defineProps({ output: Array, error: String, status: String })
defineEmits(['clear'])
const bodyEl = ref(null)
const messages = computed(() => {
const msgs = []
if (props.status) msgs.push({ type: 'info', pfx: '>', text: props.status })
for (const v of (props.output || [])) msgs.push({ type: 'output', pfx: 'OUT', text: String(v) })
if (props.error) msgs.push({ type: 'error', pfx: '!', text: props.error })
return msgs
})
watch(messages, async () => {
await nextTick()
if (bodyEl.value) bodyEl.value.scrollTop = bodyEl.value.scrollHeight
}, { deep: true })
</script>
<style scoped>
.output-console {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
overflow: hidden;
flex-shrink: 0;
}
.console-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 5px 14px;
background: var(--bg-surface);
font-size: 12px;
color: var(--text-muted);
border-bottom: 1px solid var(--border);
}
.clear-btn { padding: 2px 8px; font-size: 11px; background: transparent; color: var(--text-muted); border: 1px solid var(--border); }
.console-body {
padding: 8px 14px;
min-height: 40px;
max-height: 100px;
overflow-y: auto;
font-family: var(--font-mono);
font-size: 13px;
background: var(--bg-dark);
}
.console-line { padding: 1px 0; display: flex; gap: 8px; }
.pfx { color: var(--text-muted); flex-shrink: 0; min-width: 28px; }
.console-line.output { color: var(--accent-green); }
.console-line.error { color: var(--accent-red); }
.console-line.info { color: var(--accent-cyan); }
.empty { color: var(--text-muted); font-style: italic; font-size: 12px; }
</style>