2020-10-03 20:55:23 +08:00
|
|
|
<template>
|
2021-09-04 19:29:28 +08:00
|
|
|
<transition
|
|
|
|
name="el-message-fade"
|
|
|
|
@before-leave="onClose"
|
|
|
|
@after-leave="$emit('destroy')"
|
|
|
|
>
|
2020-10-03 20:55:23 +08:00
|
|
|
<div
|
|
|
|
v-show="visible"
|
|
|
|
:id="id"
|
|
|
|
:class="[
|
|
|
|
'el-message',
|
2021-10-27 23:17:13 +08:00
|
|
|
type && !icon ? `el-message--${type}` : '',
|
2020-10-03 20:55:23 +08:00
|
|
|
center ? 'is-center' : '',
|
|
|
|
showClose ? 'is-closable' : '',
|
|
|
|
customClass,
|
|
|
|
]"
|
|
|
|
:style="customStyle"
|
|
|
|
role="alert"
|
|
|
|
@mouseenter="clearTimer"
|
|
|
|
@mouseleave="startTimer"
|
|
|
|
>
|
2021-11-05 18:55:40 +08:00
|
|
|
<el-badge
|
|
|
|
v-if="repeatNum > 1"
|
|
|
|
:value="repeatNum"
|
|
|
|
:type="type ?? 'info'"
|
|
|
|
class="el-message__badge"
|
|
|
|
>
|
|
|
|
</el-badge>
|
2021-10-27 23:17:13 +08:00
|
|
|
<el-icon v-if="iconComponent" class="el-message__icon" :class="typeClass">
|
|
|
|
<component :is="iconComponent" />
|
|
|
|
</el-icon>
|
2020-10-03 20:55:23 +08:00
|
|
|
<slot>
|
2021-09-04 19:29:28 +08:00
|
|
|
<p v-if="!dangerouslyUseHTMLString" class="el-message__content">
|
|
|
|
{{ message }}
|
|
|
|
</p>
|
2020-10-03 20:55:23 +08:00
|
|
|
<!-- Caution here, message could've been compromised, never use user's input as message -->
|
|
|
|
<p v-else class="el-message__content" v-html="message"></p>
|
|
|
|
</slot>
|
2021-10-27 23:17:13 +08:00
|
|
|
<el-icon
|
2021-09-04 19:29:28 +08:00
|
|
|
v-if="showClose"
|
2021-10-27 23:17:13 +08:00
|
|
|
class="el-message__closeBtn"
|
2021-09-04 19:29:28 +08:00
|
|
|
@click.stop="close"
|
2021-10-27 23:17:13 +08:00
|
|
|
>
|
|
|
|
<close />
|
|
|
|
</el-icon>
|
2020-10-03 20:55:23 +08:00
|
|
|
</div>
|
|
|
|
</transition>
|
|
|
|
</template>
|
|
|
|
<script lang="ts">
|
2021-11-05 18:55:40 +08:00
|
|
|
import { defineComponent, computed, ref, onMounted, watch } from 'vue'
|
2021-09-22 01:40:18 +08:00
|
|
|
import { useEventListener, useTimeoutFn } from '@vueuse/core'
|
2021-08-24 13:36:48 +08:00
|
|
|
import { EVENT_CODE } from '@element-plus/utils/aria'
|
2021-11-05 18:55:40 +08:00
|
|
|
import ElBadge from '@element-plus/components/badge'
|
2021-10-27 23:17:13 +08:00
|
|
|
import { ElIcon } from '@element-plus/components/icon'
|
|
|
|
import { TypeComponents, TypeComponentsMap } from '@element-plus/utils/icon'
|
|
|
|
|
2021-09-22 01:40:18 +08:00
|
|
|
import { messageEmits, messageProps } from './message'
|
2021-08-24 13:36:48 +08:00
|
|
|
|
2021-09-22 01:40:18 +08:00
|
|
|
import type { CSSProperties } from 'vue'
|
|
|
|
|
2020-10-03 20:55:23 +08:00
|
|
|
export default defineComponent({
|
|
|
|
name: 'ElMessage',
|
2021-01-31 18:43:33 +08:00
|
|
|
|
2021-10-27 23:17:13 +08:00
|
|
|
components: {
|
2021-11-05 18:55:40 +08:00
|
|
|
ElBadge,
|
2021-10-27 23:17:13 +08:00
|
|
|
ElIcon,
|
|
|
|
...TypeComponents,
|
|
|
|
},
|
|
|
|
|
2021-09-22 01:40:18 +08:00
|
|
|
props: messageProps,
|
|
|
|
emits: messageEmits,
|
|
|
|
|
|
|
|
setup(props) {
|
2020-10-03 20:55:23 +08:00
|
|
|
const visible = ref(false)
|
2021-10-26 11:04:36 +08:00
|
|
|
let stopTimer: (() => void) | undefined = undefined
|
2021-09-22 01:40:18 +08:00
|
|
|
|
2021-10-27 23:17:13 +08:00
|
|
|
const typeClass = computed(() => {
|
|
|
|
const type = props.type
|
|
|
|
return type && TypeComponentsMap[type] ? `el-message-icon--${type}` : ''
|
|
|
|
})
|
|
|
|
|
|
|
|
const iconComponent = computed(() => {
|
|
|
|
return props.icon || TypeComponentsMap[props.type] || ''
|
|
|
|
})
|
|
|
|
|
2021-09-22 01:40:18 +08:00
|
|
|
const customStyle = computed<CSSProperties>(() => ({
|
|
|
|
top: `${props.offset}px`,
|
|
|
|
zIndex: props.zIndex,
|
|
|
|
}))
|
2021-01-31 18:43:33 +08:00
|
|
|
|
|
|
|
function startTimer() {
|
|
|
|
if (props.duration > 0) {
|
2021-10-26 11:04:36 +08:00
|
|
|
;({ stop: stopTimer } = useTimeoutFn(() => {
|
2021-09-22 01:40:18 +08:00
|
|
|
if (visible.value) close()
|
|
|
|
}, props.duration))
|
2020-10-03 20:55:23 +08:00
|
|
|
}
|
2021-01-31 18:43:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
function clearTimer() {
|
2021-10-26 11:04:36 +08:00
|
|
|
stopTimer?.()
|
2021-01-31 18:43:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
function close() {
|
|
|
|
visible.value = false
|
|
|
|
}
|
|
|
|
|
|
|
|
function keydown({ code }: KeyboardEvent) {
|
2020-10-04 14:49:39 +08:00
|
|
|
if (code === EVENT_CODE.esc) {
|
2020-10-03 20:55:23 +08:00
|
|
|
// press esc to close the message
|
2021-01-31 18:43:33 +08:00
|
|
|
if (visible.value) {
|
|
|
|
close()
|
2020-10-03 20:55:23 +08:00
|
|
|
}
|
|
|
|
} else {
|
2021-01-31 18:43:33 +08:00
|
|
|
startTimer() // resume timer
|
2020-10-03 20:55:23 +08:00
|
|
|
}
|
2021-01-31 18:43:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
startTimer()
|
|
|
|
visible.value = true
|
|
|
|
})
|
|
|
|
|
2021-11-05 18:55:40 +08:00
|
|
|
watch(
|
|
|
|
() => props.repeatNum,
|
|
|
|
() => {
|
|
|
|
clearTimer()
|
|
|
|
startTimer()
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2021-09-22 01:40:18 +08:00
|
|
|
useEventListener(document, 'keydown', keydown)
|
2021-01-31 18:43:33 +08:00
|
|
|
|
|
|
|
return {
|
|
|
|
typeClass,
|
2021-10-27 23:17:13 +08:00
|
|
|
iconComponent,
|
2021-01-31 18:43:33 +08:00
|
|
|
customStyle,
|
|
|
|
visible,
|
|
|
|
|
|
|
|
close,
|
|
|
|
clearTimer,
|
|
|
|
startTimer,
|
|
|
|
}
|
2020-10-03 20:55:23 +08:00
|
|
|
},
|
|
|
|
})
|
|
|
|
</script>
|