|
@@ -0,0 +1,120 @@
|
|
|
|
+<script setup lang="ts">
|
|
|
|
+import { type Msg, useMessagePipeStore } from '@/stores/msg.ts'
|
|
|
|
+import { computed, onMounted, onUnmounted, ref } from 'vue'
|
|
|
|
+import { delay } from '@/utils'
|
|
|
|
+import { failedIcon, infoIcon, successIcon, warningIcon } from '@/assets/icons.ts'
|
|
|
|
+
|
|
|
|
+const props = defineProps<{
|
|
|
|
+ target: Msg
|
|
|
|
+}>()
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+const prefixIcon = computed(() => {
|
|
|
|
+ switch (props.target.type) {
|
|
|
|
+ case 'danger':
|
|
|
|
+ return failedIcon
|
|
|
|
+ case 'warning':
|
|
|
|
+ return warningIcon
|
|
|
|
+ case 'info':
|
|
|
|
+ return infoIcon
|
|
|
|
+ case 'success':
|
|
|
|
+ return successIcon
|
|
|
|
+ default:
|
|
|
|
+ return infoIcon
|
|
|
|
+ }
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+function baseColor() {
|
|
|
|
+ switch (props.target.type) {
|
|
|
|
+ case 'danger':
|
|
|
|
+ return '#ff4c4c'
|
|
|
|
+ case 'warning':
|
|
|
|
+ return '#ffbb70'
|
|
|
|
+ case 'info':
|
|
|
|
+ return '#ffffff'
|
|
|
|
+ case 'success':
|
|
|
|
+ return '#ffffff'
|
|
|
|
+ default:
|
|
|
|
+ return '#ffffff'
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const buttonLineStyle = ref({
|
|
|
|
+ width: '100%',
|
|
|
|
+ backgroundColor: baseColor(),
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+const cardStyle = ref({
|
|
|
|
+ height: '0',
|
|
|
|
+ marginBottom: '12px',
|
|
|
|
+ color: baseColor(),
|
|
|
|
+ fill: baseColor(),
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+let lock = false
|
|
|
|
+
|
|
|
|
+async function onUpdate() {
|
|
|
|
+ if (lock) return
|
|
|
|
+ if (useMessagePipeStore().pipe[0].key == props.target.key) {
|
|
|
|
+ lock = true
|
|
|
|
+ buttonLineStyle.value.width = '0'
|
|
|
|
+ await delay(5000)
|
|
|
|
+ cardStyle.value.height = '0'
|
|
|
|
+ cardStyle.value.marginBottom = '0'
|
|
|
|
+ await delay(320)
|
|
|
|
+ useMessagePipeStore().pop()
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+onMounted(async () => {
|
|
|
|
+ useMessagePipeStore().submit(onUpdate)
|
|
|
|
+ await delay(20)
|
|
|
|
+ cardStyle.value.height = '30px'
|
|
|
|
+ onUpdate()
|
|
|
|
+})
|
|
|
|
+
|
|
|
|
+onUnmounted(() => {
|
|
|
|
+ useMessagePipeStore().unsubmit(onUpdate)
|
|
|
|
+})
|
|
|
|
+</script>
|
|
|
|
+
|
|
|
|
+<template>
|
|
|
|
+ <div class="msg-card" :style="cardStyle">
|
|
|
|
+ <div class="bottom-line" :style="buttonLineStyle" />
|
|
|
|
+ <div class="card-content">
|
|
|
|
+ <div class="prefix-icon" v-html="prefixIcon.template"/>
|
|
|
|
+ <div class="card-text">{{ props.target.message }}</div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<style scoped>
|
|
|
|
+.bottom-line {
|
|
|
|
+ position: absolute;
|
|
|
|
+ bottom: 0;
|
|
|
|
+ left: 0;
|
|
|
|
+ width: 100%;
|
|
|
|
+ height: 2px;
|
|
|
|
+ transition: width 5s;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.msg-card {
|
|
|
|
+ overflow: hidden;
|
|
|
|
+ padding-left: 12px;
|
|
|
|
+ position: relative;
|
|
|
|
+ padding-right: 12px;
|
|
|
|
+ transition: all 0.3s;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.card-content {
|
|
|
|
+ display: flex;
|
|
|
|
+ align-items: center;
|
|
|
|
+ gap: 12px;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+.card-content .prefix-icon {
|
|
|
|
+ width: 24px;
|
|
|
|
+ height: 24px;
|
|
|
|
+}
|
|
|
|
+</style>
|