Merge pull request #66 from Chanzhaoyu/dialog-components
perf: 优化 dilog 下组件
This commit is contained in:
commit
9da5f780db
@ -1,83 +1,65 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="ConfirmDialog" @click="$emit('dismiss')" v-if="visible">
|
<div class="ConfirmDialog" @click="onDismiss" v-if="visible">
|
||||||
<div class="content" @click.stop="stop">
|
<div class="content">
|
||||||
<slot name="header"></slot>
|
<slot name="header"></slot>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<div class="title" v-if="title">{{ title }}</div>
|
<div class="title" v-if="title">{{ title }}</div>
|
||||||
<div class="subtitle" :class="subtitleColor" v-if="subtitle">
|
<div :class="['subtitle', subtitleColor]" v-if="subtitle">
|
||||||
{{ subtitle }}
|
{{ subtitle }}
|
||||||
</div>
|
</div>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<div class="cancel" :class="cancelTextColor" @click.stop="cancel">
|
<div :class="['cancel', cancelTextColor]" @click.stop="onCancel">
|
||||||
{{ cancelText }}
|
{{ cancelText }}
|
||||||
</div>
|
</div>
|
||||||
<div class="ok" @click.stop="ok">{{ okText }}</div>
|
<div class="ok" @click.stop="onOk">{{ okText }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
|
||||||
/*TODO 单独使用时,没有mark*/
|
<script setup lang="ts">
|
||||||
export default {
|
defineOptions({ name: 'ConfirmDialog' })
|
||||||
name: 'ConfirmDialog',
|
|
||||||
props: {
|
interface Props {
|
||||||
visible: {
|
title?: string
|
||||||
type: Boolean,
|
subtitle?: string
|
||||||
default: true
|
subtitleColor?: string
|
||||||
},
|
okText?: string
|
||||||
title: {
|
cancelText?: string
|
||||||
type: String,
|
cancelTextColor?: string
|
||||||
default() {
|
|
||||||
return ''
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
subtitle: {
|
withDefaults(defineProps<Props>(), {
|
||||||
type: String,
|
title: '',
|
||||||
default() {
|
subtitle: '',
|
||||||
return ''
|
subtitleColor: 'gray',
|
||||||
}
|
okText: '确定',
|
||||||
},
|
cancelText: '取消',
|
||||||
subtitleColor: {
|
cancelTextColor: 'gray'
|
||||||
type: String,
|
})
|
||||||
default() {
|
|
||||||
return 'gray'
|
const emit = defineEmits<{
|
||||||
}
|
(ev: 'ok'): void
|
||||||
},
|
(ev: 'cancel'): void
|
||||||
okText: {
|
(ev: 'dismiss'): void
|
||||||
type: String,
|
}>()
|
||||||
default() {
|
|
||||||
return '确定'
|
const visible = defineModel<boolean>('visible', { type: Boolean, default: true })
|
||||||
}
|
|
||||||
},
|
const onOk = () => {
|
||||||
cancelText: {
|
visible.value = false
|
||||||
type: String,
|
emit('ok')
|
||||||
default() {
|
|
||||||
return '取消'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
cancelTextColor: {
|
|
||||||
type: String,
|
|
||||||
default() {
|
|
||||||
return 'gray'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
stop() {},
|
|
||||||
ok() {
|
|
||||||
this.$emit('ok')
|
|
||||||
this.$emit('update:visible', false)
|
|
||||||
},
|
|
||||||
cancel() {
|
|
||||||
this.$emit('cancel')
|
|
||||||
this.$emit('update:visible', false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onCancel = () => {
|
||||||
|
visible.value = false
|
||||||
|
emit('cancel')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onDismiss = () => {
|
||||||
|
emit('dismiss')
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -3,16 +3,9 @@
|
|||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
|
||||||
export default {
|
<script setup lang="ts">
|
||||||
name: 'FadeDialog',
|
defineOptions({ name: 'FadeDialog' })
|
||||||
data() {
|
|
||||||
return {}
|
|
||||||
},
|
|
||||||
computed: {},
|
|
||||||
created() {},
|
|
||||||
methods: {}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
|
|||||||
@ -1,17 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- <transition> -->
|
|
||||||
<Transition name="test">
|
<Transition name="test">
|
||||||
<div
|
<div
|
||||||
ref="dialog"
|
ref="dialog"
|
||||||
class="FromBottomDialog"
|
|
||||||
v-if="modelValue"
|
v-if="modelValue"
|
||||||
:class="[mode, showHengGang ? '' : 'no-heng-gang']"
|
:class="['FromBottomDialog', mode, showHengGang ? '' : 'no-heng-gang']"
|
||||||
@touchstart="start"
|
@touchstart="onStart"
|
||||||
@touchmove="move"
|
@touchmove="onMove"
|
||||||
@touchend="end"
|
@touchend="onEnd"
|
||||||
>
|
>
|
||||||
<slot name="header"></slot>
|
<slot name="header"></slot>
|
||||||
<div class="heng-gang" :class="mode" v-if="showHengGang">
|
<div :class="['heng-gang', mode]" v-if="showHengGang">
|
||||||
<div class="content"></div>
|
<div class="content"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="wrapper" ref="wrapper">
|
<div class="wrapper" ref="wrapper">
|
||||||
@ -20,74 +18,82 @@
|
|||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch } from 'vue'
|
||||||
import Dom, { _css } from '../../utils/dom'
|
import Dom, { _css } from '../../utils/dom'
|
||||||
import bus, { EVENT_KEY } from '@/utils/bus'
|
import bus, { EVENT_KEY } from '@/utils/bus'
|
||||||
import { _stopPropagation } from '@/utils'
|
import { _stopPropagation } from '@/utils'
|
||||||
|
|
||||||
export default {
|
defineOptions({ name: 'FromBottomDialog' })
|
||||||
name: 'FromBottomDialog',
|
|
||||||
props: {
|
interface Props {
|
||||||
modelValue: {
|
mode?: 'dark' | 'light' | 'white'
|
||||||
type: Boolean,
|
maskMode?: 'dark' | 'light' | 'white'
|
||||||
default: false
|
height?: string
|
||||||
},
|
showHengGang?: boolean
|
||||||
mode: {
|
pageId: string | null
|
||||||
type: String,
|
borderRadius?: string
|
||||||
default: 'dark'
|
tag?: string
|
||||||
// default: 'light'
|
|
||||||
// default: 'white'
|
|
||||||
},
|
|
||||||
maskMode: {
|
|
||||||
type: String,
|
|
||||||
default: 'dark'
|
|
||||||
},
|
|
||||||
height: {
|
|
||||||
type: String,
|
|
||||||
default: 'calc(var(--vh, 1vh) * 70)'
|
|
||||||
},
|
|
||||||
showHengGang: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
pageId: {
|
|
||||||
type: String,
|
|
||||||
default: null,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
borderRadius: {
|
|
||||||
type: String,
|
|
||||||
default: '15rem 15rem 0 0'
|
|
||||||
},
|
|
||||||
tag: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
watch: {
|
interface Emits {
|
||||||
modelValue(newVal) {
|
(ev: 'cancel'): void
|
||||||
let page = document.getElementById(this.pageId)
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
mode: 'dark',
|
||||||
|
maskMode: 'dark',
|
||||||
|
height: 'calc(var(--vh, 1vh) * 70)',
|
||||||
|
showHengGang: true,
|
||||||
|
pageId: null,
|
||||||
|
borderRadius: '15rem 15rem 0 0',
|
||||||
|
tag: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>()
|
||||||
|
|
||||||
|
const modelValue = defineModel<boolean>('value', { type: Boolean, default: false })
|
||||||
|
|
||||||
|
const dialog = ref<HTMLElement | null>(null)
|
||||||
|
|
||||||
|
const wrapper = ref<HTMLElement | null>(null)
|
||||||
|
|
||||||
|
const scroll = ref(0)
|
||||||
|
|
||||||
|
const startY = ref(0)
|
||||||
|
|
||||||
|
const moveY = ref(0)
|
||||||
|
|
||||||
|
const startTime = ref(0)
|
||||||
|
|
||||||
|
const pagePosition = ref(null)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => modelValue.value,
|
||||||
|
(newVal: boolean) => {
|
||||||
|
let page = document.getElementById(props.pageId)
|
||||||
if (!page) return
|
if (!page) return
|
||||||
if (newVal) {
|
if (newVal) {
|
||||||
this.pagePosition = _css(page, 'position')
|
pagePosition.value = _css(page, 'position')
|
||||||
page.style.position = 'absolute'
|
page.style.position = 'absolute'
|
||||||
this.scroll = document.documentElement.scrollTop
|
scroll.value = document.documentElement.scrollTop
|
||||||
document.body.style.position = 'fixed'
|
document.body.style.position = 'fixed'
|
||||||
document.body.style.top = -this.scroll + 'px'
|
document.body.style.top = -scroll.value + 'px'
|
||||||
|
|
||||||
let maskTemplate = `<div class="Mask fade-in ${this.maskMode}"></div>`
|
let maskTemplate = `<div class="Mask fade-in ${props.maskMode}"></div>`
|
||||||
let mask = new Dom().create(maskTemplate)
|
let mask = new Dom().create(maskTemplate)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
mask.on('click', (e) => {
|
mask.on('click', (e: Event) => {
|
||||||
_stopPropagation(e)
|
_stopPropagation(e)
|
||||||
this.hide(false)
|
onHide()
|
||||||
})
|
})
|
||||||
}, 200)
|
}, 200)
|
||||||
page.appendChild(mask.els[0])
|
page.appendChild(mask.els[0])
|
||||||
} else {
|
} else {
|
||||||
page.style.position = this.pagePosition || 'fixed'
|
page.style.position = pagePosition.value || 'fixed'
|
||||||
document.body.style.position = 'static'
|
document.body.style.position = 'static'
|
||||||
document.documentElement.scrollTop = this.scroll
|
document.documentElement.scrollTop = scroll.value
|
||||||
|
|
||||||
let mask = new Dom('.Mask').replaceClass('fade-in', 'fade-out')
|
let mask = new Dom('.Mask').replaceClass('fade-in', 'fade-out')
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -95,55 +101,45 @@ export default {
|
|||||||
}, 250)
|
}, 250)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
)
|
||||||
data() {
|
|
||||||
return {
|
const onHide = () => {
|
||||||
scroll: 0,
|
modelValue.value = false
|
||||||
startY: 0,
|
emit('cancel')
|
||||||
moveY: 0,
|
|
||||||
startTime: 0,
|
|
||||||
pagePosition: null
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
computed: {},
|
const onStart = (e: TouchEvent) => {
|
||||||
created() {},
|
if (wrapper.value?.scrollTop !== 0) return
|
||||||
methods: {
|
startY.value = e.touches[0].clientY
|
||||||
hide(val = false) {
|
startTime.value = Date.now()
|
||||||
this.$emit('update:modelValue', val)
|
_css(dialog.value, 'transition-duration', '0ms')
|
||||||
this.$emit('cancel')
|
}
|
||||||
},
|
|
||||||
start(e) {
|
const onMove = (e: TouchEvent) => {
|
||||||
if (this.$refs.wrapper.scrollTop !== 0) return
|
if (wrapper.value?.scrollTop !== 0) return
|
||||||
this.startY = e.touches[0].pageY
|
moveY.value = e.touches[0].pageY - startY.value
|
||||||
this.startTime = Date.now()
|
if (moveY.value < 0) {
|
||||||
_css(this.$refs.dialog, 'transition-duration', `0ms`)
|
|
||||||
},
|
|
||||||
move(e) {
|
|
||||||
if (this.$refs.wrapper.scrollTop !== 0) return
|
|
||||||
this.moveY = e.touches[0].pageY - this.startY
|
|
||||||
if (this.moveY > 0) {
|
|
||||||
bus.emit(EVENT_KEY.DIALOG_MOVE, {
|
bus.emit(EVENT_KEY.DIALOG_MOVE, {
|
||||||
tag: this.tag,
|
tag: props.tag,
|
||||||
e: this.moveY
|
e: moveY.value
|
||||||
})
|
})
|
||||||
_css(this.$refs.dialog, 'transform', `translate3d(0,${this.moveY}px,0)`)
|
_css(dialog.value, 'transform', `translate3d(0, ${moveY.value}px, 0)`)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
end() {
|
|
||||||
|
const onEnd = () => {
|
||||||
// 如果是外部改变 modelValue 值的话,这里会没有 ref
|
// 如果是外部改变 modelValue 值的话,这里会没有 ref
|
||||||
if (!this.$refs.dialog) return
|
if (!dialog.value) return
|
||||||
if (Date.now() - this.startTime < 150 && Math.abs(this.moveY) < 30) return
|
if (Date.now() - startTime.value < 150 && Math.abs(moveY.value) < 30) return
|
||||||
let clientHeight = this.$refs.dialog.clientHeight
|
let clientHeight = dialog.value?.clientHeight
|
||||||
_css(this.$refs.dialog, 'transition-duration', `250ms`)
|
_css(dialog.value, 'transition-duration', `250ms`)
|
||||||
if (Math.abs(this.moveY) > clientHeight / 2) {
|
if (Math.abs(moveY.value) > clientHeight / 2) {
|
||||||
_css(this.$refs.dialog, 'transform', `translate3d(0,100%,0)`)
|
_css(dialog.value, 'transform', `translate3d(0,100%,0)`)
|
||||||
bus.emit(EVENT_KEY.DIALOG_END, { tag: this.tag, isClose: true })
|
bus.emit(EVENT_KEY.DIALOG_END, { tag: props.tag, isClose: true })
|
||||||
setTimeout(this.hide, 250)
|
setTimeout(onHide, 250)
|
||||||
} else {
|
} else {
|
||||||
_css(this.$refs.dialog, 'transform', `translate3d(0,0,0)`)
|
_css(dialog.value, 'transform', `translate3d(0,0,0)`)
|
||||||
bus.emit(EVENT_KEY.DIALOG_END, { tag: this.tag, isClose: false })
|
bus.emit(EVENT_KEY.DIALOG_END, { tag: props.tag, isClose: false })
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,57 +1,51 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="NoticeDialog" @click="$emit('dismiss')">
|
<div class="NoticeDialog" @click="onDismiss">
|
||||||
<div class="content" @click.stop="stop">
|
<div class="content">
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<div class="title">{{ title }}</div>
|
<div class="title">{{ title }}</div>
|
||||||
<div class="subtitle" :class="subtitleColor" v-if="subtitle">
|
<div :class="['subtitle', subtitleColor]" v-if="subtitle">
|
||||||
{{ subtitle }}
|
{{ subtitle }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<div class="cancel" @click.stop="$emit('cancel')">{{ cancelText }}</div>
|
<div class="cancel" @click.stop="onCancel">{{ cancelText }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
|
||||||
export default {
|
<script setup lang="ts">
|
||||||
name: 'NoticeDialog',
|
defineOptions({ name: 'NoticeDialog' })
|
||||||
props: {
|
|
||||||
visible: {
|
interface Props {
|
||||||
type: Boolean,
|
title?: string
|
||||||
default: false
|
subtitle?: string
|
||||||
},
|
subtitleColor?: string
|
||||||
title: {
|
cancelText?: string
|
||||||
type: String,
|
|
||||||
default() {
|
|
||||||
return ''
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
subtitle: {
|
withDefaults(defineProps<Props>(), {
|
||||||
type: String,
|
title: '',
|
||||||
default() {
|
subtitle: '',
|
||||||
return ''
|
subtitleColor: 'gray',
|
||||||
}
|
cancelText: '取消'
|
||||||
},
|
})
|
||||||
subtitleColor: {
|
|
||||||
type: String,
|
const emit = defineEmits<{
|
||||||
default() {
|
(ev: 'ok'): void
|
||||||
return 'gray'
|
(ev: 'cancel'): void
|
||||||
}
|
(ev: 'dismiss'): void
|
||||||
},
|
}>()
|
||||||
cancelText: {
|
|
||||||
type: String,
|
const visible = defineModel<boolean>('visible', { type: Boolean, default: true })
|
||||||
default() {
|
|
||||||
return '取消'
|
const onCancel = () => {
|
||||||
}
|
visible.value = false
|
||||||
}
|
emit('cancel')
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
stop() {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onDismiss = () => {
|
||||||
|
emit('dismiss')
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -1,30 +1,39 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="SelectDialog" @click="$emit('cancel')">
|
<div class="SelectDialog" @click="onCancel">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="item" :key="i" v-for="(item, i) in list" @click.stop="$emit('ok', item)">
|
<div class="item" :key="i" v-for="(item, i) in list" @click.stop="onOk(item)">
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
|
||||||
export default {
|
<script setup lang="ts" generic="T">
|
||||||
name: 'SelectDialog',
|
defineOptions({ name: 'SelectDialog' })
|
||||||
props: {
|
|
||||||
visible: {
|
type Item = { name: string } & T
|
||||||
type: Boolean,
|
|
||||||
default: false
|
interface Props {
|
||||||
},
|
visible?: boolean
|
||||||
list: {
|
list?: Item[]
|
||||||
type: Array,
|
|
||||||
default() {
|
|
||||||
return []
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
withDefaults(defineProps<Props>(), {
|
||||||
|
visible: false,
|
||||||
|
list: () => []
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(ev: 'ok', item: Item): void
|
||||||
|
(ev: 'cancel'): void
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const onOk = (item: Item) => {
|
||||||
|
emit('ok', item)
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data() {
|
const onCancel = () => {
|
||||||
return {}
|
emit('cancel')
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -1,47 +1,50 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="SimpleConfirmDialog" @click="$emit('dismiss')">
|
<div class="SimpleConfirmDialog" @click="onDismiss">
|
||||||
<div class="content" @click.stop="stop">
|
<div class="content">
|
||||||
<div class="item">{{ title }}</div>
|
<div class="item">{{ title }}</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<div class="cancel" @click.stop="$emit('cancel')">{{ cancelText }}</div>
|
<div class="cancel" @click.stop="onCancel">{{ cancelText }}</div>
|
||||||
<div class="ok" @click.stop="$emit('ok')">{{ okText }}</div>
|
<div class="ok" @click.stop="onOk">{{ okText }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
|
||||||
export default {
|
<script setup lang="ts">
|
||||||
name: 'SimpleConfirmDialog',
|
defineOptions({ name: 'SimpleConfirmDialog' })
|
||||||
props: {
|
|
||||||
visible: {
|
interface Props {
|
||||||
type: Boolean,
|
title?: string
|
||||||
default: false
|
okText?: string
|
||||||
},
|
cancelText?: string
|
||||||
title: {
|
|
||||||
type: String,
|
|
||||||
default() {
|
|
||||||
return ''
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
okText: {
|
withDefaults(defineProps<Props>(), {
|
||||||
type: String,
|
title: '',
|
||||||
default() {
|
okText: '确定',
|
||||||
return '保存'
|
cancelText: '取消'
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(ev: 'ok'): void
|
||||||
|
(ev: 'cancel'): void
|
||||||
|
(ev: 'dismiss'): void
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const visible = defineModel<boolean>('visible', { type: Boolean, default: true })
|
||||||
|
|
||||||
|
const onOk = () => {
|
||||||
|
visible.value = false
|
||||||
|
emit('ok')
|
||||||
}
|
}
|
||||||
},
|
|
||||||
cancelText: {
|
const onCancel = () => {
|
||||||
type: String,
|
visible.value = false
|
||||||
default() {
|
emit('cancel')
|
||||||
return '放弃'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
stop() {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onDismiss = () => {
|
||||||
|
emit('dismiss')
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user