AutoTeam-F / web /src /components /ToastHost.vue
ZRainbow's picture
feat: AutoTeam 大版本升级:安全轮换、并行、IPv6、指纹加固与前端重构
1f4cfcb
Raw
History Blame Contribute Delete
1.88 kB
<!--
ToastHost — toast 容器,挂在 App 顶层
-->
<template>
<div class="fixed top-3 right-3 z-[100] space-y-2 max-w-sm pointer-events-none">
<transition-group tag="div" class="space-y-2">
<div v-for="t in state.items" :key="t.id"
class="pointer-events-auto rounded-lg border bg-surface shadow-card px-4 py-3 flex items-start gap-3"
:class="[toneClass(t.tone), t.leaving ? 'animate-toast-out' : 'animate-toast-in']"
@click="dismiss(t.id)">
<span class="shrink-0 mt-0.5">
<Check v-if="t.tone === 'success'" class="w-4 h-4 text-emerald-700" :stroke-width="2" />
<X v-else-if="t.tone === 'error'" class="w-4 h-4 text-rose-700" :stroke-width="2" />
<TriangleAlert v-else-if="t.tone === 'warning'" class="w-4 h-4 text-amber-700" :stroke-width="2" />
<Info v-else class="w-4 h-4 text-sky-700" :stroke-width="2" />
</span>
<div class="flex-1 min-w-0">
<div class="text-sm font-semibold leading-tight" :class="titleColor(t.tone)">{{ t.text }}</div>
<div v-if="t.detail" class="text-xs mt-1 opacity-70 break-all" :class="titleColor(t.tone)">{{ t.detail }}</div>
</div>
</div>
</transition-group>
</div>
</template>
<script setup>
import { useToast } from '../composables/useToast.js'
import { Check, Info, TriangleAlert, X } from 'lucide-vue-next'
const { state, dismiss } = useToast()
function toneClass(tone) {
return {
success: 'bg-emerald-50 border-emerald-200',
error: 'bg-rose-50 border-rose-200',
warning: 'bg-amber-50 border-amber-200',
info: 'bg-sky-50 border-sky-200',
}[tone] || 'bg-sky-50 border-sky-200'
}
function titleColor(tone) {
return {
success: 'text-emerald-900',
error: 'text-rose-900',
warning: 'text-amber-900',
info: 'text-sky-900',
}[tone] || 'text-sky-900'
}
</script>