Files

106 lines
2.4 KiB
Vue

<template>
<Teleport to="body">
<Transition name="viewer">
<div
v-if="visible"
class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm p-4"
@click="close"
>
<div
class="card w-full max-w-md p-6"
@click.stop
>
<!-- 标题 -->
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">
{{ title }}
</h3>
<button
@click="close"
class="text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 transition-colors"
>
<Icon name="heroicons:x-mark" class="w-5 h-5" />
</button>
</div>
<!-- 内容 -->
<div class="mb-6">
<slot></slot>
</div>
<!-- 按钮 -->
<div v-if="showCancel || showConfirm" class="flex justify-end gap-3">
<button
v-if="showCancel"
@click="close"
class="btn-secondary"
>
{{ cancelText }}
</button>
<button
v-if="showConfirm"
@click="confirm"
:class="confirmClass"
:disabled="confirmDisabled"
>
{{ confirmText }}
</button>
</div>
</div>
</div>
</Transition>
</Teleport>
</template>
<script setup>
const props = defineProps({
visible: {
type: Boolean,
default: false
},
title: {
type: String,
default: '提示'
},
showCancel: {
type: Boolean,
default: true
},
showConfirm: {
type: Boolean,
default: true
},
cancelText: {
type: String,
default: '取消'
},
confirmText: {
type: String,
default: '确定'
},
confirmType: {
type: String,
default: 'primary' // 'primary' | 'danger'
},
confirmDisabled: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['close', 'confirm'])
const confirmClass = computed(() => {
const baseClass = props.confirmType === 'danger' ? 'btn-danger' : 'btn-primary'
return props.confirmDisabled ? `${baseClass} opacity-50 cursor-not-allowed` : baseClass
})
const close = () => {
emit('close')
}
const confirm = () => {
emit('confirm')
}
</script>