<!-- 全局提示容器，负责展示、暂停、关闭和复制不同状态的临时消息。 -->
<script setup lang="ts">
import { computed, onBeforeUnmount, reactive, watch } from "vue";
import { Check, Close, CopyDocument, InfoFilled, WarningFilled } from "@element-plus/icons-vue";
import { useToastStore, type ToastItem } from "@/stores/toast";
const store = useToastStore(),
  elapsed = reactive<Record<number, number>>({}),
  paused = reactive<Record<number, boolean>>({});
let last = performance.now();
const timer = setInterval(() => {
  const now = performance.now(),
    delta = now - last;
  last = now;
  for (const item of store.visible) {
    if (!paused[item.id]) elapsed[item.id] = (elapsed[item.id] || 0) + delta;
    if (elapsed[item.id] >= item.duration) store.remove(item.id);
  }
}, 50);
watch(
  () => store.visible.map((i) => i.id),
  (ids) =>
    ids.forEach((id) => {
      if (elapsed[id] === undefined) elapsed[id] = 0;
    }),
);
onBeforeUnmount(() => clearInterval(timer));
const icons = { success: Check, warning: WarningFilled, error: WarningFilled, info: InfoFilled };
// 计算提示剩余时长比例，供进度条使用合成层动画展示。
const progress = (item: ToastItem) =>
  computed(() => Math.max(0, 1 - (elapsed[item.id] || 0) / item.duration)).value;
// 复制错误消息的完整内容，便于用户反馈或排查问题。
async function copy(item: ToastItem) {
  await navigator.clipboard.writeText(item.copyText || item.message);
}
</script>
<template>
  <div class="toast-region">
    <TransitionGroup name="toast-fade"
      ><section
        v-for="item in store.visible"
        :key="item.id"
        class="app-toast"
        :class="`app-toast--${item.type}`"
        @mouseenter="paused[item.id] = true"
        @mouseleave="paused[item.id] = false"
      >
        <el-icon><component :is="icons[item.type]" /></el-icon>
        <div class="app-toast__copy">
          <strong>{{ item.title }}</strong
          ><span>{{ item.message }}</span>
        </div>
        <button
          v-if="item.type === 'error'"
          class="icon-button"
          title="复制完整错误"
          @click="copy(item)"
        >
          <el-icon><CopyDocument /></el-icon></button
        ><button
          class="icon-button"
          title="关闭提示"
          @click="store.remove(item.id)"
        >
          <el-icon><Close /></el-icon>
        </button>
        <div
          class="app-toast__progress"
          :style="{ '--toast-progress': progress(item) }"
        /></section
    ></TransitionGroup>
  </div>
</template>
