Files
Scoreboard/web/src/admin/components/ToastHost.vue
T
AskaEth bc8b1ee6c0 feat: M3-M7 全模块落地 + 集成接线
- M3 认证/权限/审计/限流 + 全部 REST 接口
- M4 管理面板(MIUIx + 成绩录入/积分榜下钻/大屏控制)
- M5a 大屏页面(六页 + 明细覆盖层 + 缩放适配)
- M6 WebSocket 实时同步中心
- M7 xlsx 导出 + 赛事包 zip + 备份
- 规则包 YAML 导入导出(差异预览)
- 字体 vendor 子集化(4 套 x2 字重)
- 集成:realtime/export/rules 接入 main+httpapi;backup 子命令
- 修复:中间件包装 ResponseWriter 丢失 Hijacker,导致 WS 握手 501
2026-09-09 19:02:24 +08:00

52 lines
1.1 KiB
Vue

<script setup lang="ts">
import { useToastStore, type ToastKind } from '../stores/toast'
import MxIcon from './MxIcon.vue'
import type { IconName } from './icons'
const toast = useToastStore()
const ICONS: Record<ToastKind, IconName> = {
success: 'check',
warning: 'warning',
error: 'warning',
info: 'bell',
}
</script>
<template>
<div class="mx-toast-container">
<div
v-for="item in toast.items"
:key="item.id"
class="mx-toast show"
:class="`mx-toast-${item.kind}`"
role="status"
>
<span class="mx-toast-icon"><MxIcon :name="ICONS[item.kind]" :size="18" /></span>
<span class="mx-toast-text">
{{ item.message }}
<small v-if="item.detail">{{ item.detail }}</small>
</span>
<button class="mx-toast-close" type="button" @click="toast.dismiss(item.id)">
<MxIcon name="close" :size="14" />
</button>
</div>
</div>
</template>
<style scoped>
.mx-toast {
position: relative;
}
.mx-toast-text {
display: flex;
flex-direction: column;
line-height: 1.35;
}
.mx-toast-text small {
font-size: 11px;
font-weight: 400;
color: var(--mx-t3);
}
</style>