组件:
<template>
<teleport v-if="appendToBody" to="body">
<transition name="dialog-fade">
<div
v-show="visible"
class="dialog-overlay"
:class="customClass"
@click.self="handleCloseModal"
>
<div class="dialog-content" :style="dialogStyle" @click.stop>
<div class="dialog-header">
<div class="title-content">
<span>{{ title }}33</span>
<i class="iconfont guanbi"></i>
</div>
</div>
<div class="mes-dialog-layout-main">
<slot></slot>
</div>
<div class="dialog-btn" v-if="showCancel && showConfirm">
<div
v-if="showCancel && !slots['cancelText']"
class="dialog-button-cancel"
@click="handleCancel"
>
<!-- 使用 cancelText -->
{{ cancelText }}
</div>
<div v-else @click="handleCancel">
<!-- 使用自定义插槽 -->
<slot :name="'cancelText'"></slot>
</div>
<div
v-if="showConfirm && !slots['confirmText']"
class="dialog-button-confirm"
@click="handleSure"
>
<!-- 使用 confirmText -->
{{ confirmText }}
</div>
<div v-else @click="handleSure">
<!-- 使用自定义插槽 -->
<slot :name="'confirmText'"></slot>
</div>
</div>
</div>
</div>
</transition>
</teleport>
<transition name="dialog-fade" v-else>
<div
v-show="visible"
class="dialog-overlay"
:class="customClass"
@click.self="handleCloseModal"
>
<div class="dialog-content" :style="dialogStyle" @click.stop>
<div class="dialog-header">
<div class="title-content">
<span>{{ title }}11</span>
</div>
</div>
<div class="mes-dialog-layout-main">
<slot></slot>
</div>
<div class="dialog-btn" v-if="showCancel && showConfirm">
<div
v-if="showCancel && !slots['cancelText']"
class="dialog-button-cancel"
@click="handleCancel"
>
<!-- 使用 cancelText -->
{{ cancelText }}
</div>
<div v-else @click="handleCancel">
<!-- 使用自定义插槽 -->
<slot :name="'cancelText'"></slot>
</div>
<div
v-if="showConfirm && !slots['confirmText']"
class="dialog-button-confirm"
@click="handleSure"
>
<!-- 使用 confirmText -->
{{ confirmText }}
</div>
<div v-else @click="handleSure">
<!-- 使用自定义插槽 -->
<slot :name="'confirmText'"></slot>
</div>
</div>
</div>
</div>
</transition>
</template>
<script lang="ts" setup>
import { ref, watch, computed, useSlots } from 'vue'
const slots = useSlots()
const props = withDefaults(
defineProps<{
modelValue?: boolean
width?: string
height?: string
top?: string
title?: string
appendToBody?: boolean
closeOnClickModal?: boolean
showConfirm?: boolean
showCancel?: boolean
cancelText?: string
confirmText?: string
customClass?: string
}>(),
{
modelValue: false,
width: '30%',
height: 'auto',
top: '10%',
title: '',
appendToBody: true,
closeOnClickModal: false,
showConfirm: true,
showCancel: true,
cancelText: '取消',
confirmText: '确认',
customClass: '',
},
)
const emit = defineEmits<{
(event: 'update:modelValue', value: boolean): void
(event: 'beforeClose'): void
(event: 'on-cancel'): void
(event: 'on-sure'): void
}>()
const visible = ref(props.modelValue)
watch(
() => props.modelValue,
(newVal) => {
visible.value = newVal
},
)
const dialogStyle = computed(() => ({
width: props.width,
height: props.height,
marginTop: props.top,
}))
function handleCloseModal() {
if (props.closeOnClickModal) {
handleClose()
}
}
function handleClose() {
emit('beforeClose')
emit('update:modelValue', false)
}
function handleCancel() {
emit('on-cancel')
}
function handleSure() {
emit('on-sure')
}
</script>
<style lang="scss" scoped>
.iconfont {
margin-right: 15.63rpx;
font-size: 10.16rpx;
}
.dialog-overlay {
position: fixed;
inset: 0;
z-index: 9999;
height: 100%;
overflow: auto;
// background-color: rgba(0, 0, 0, 0.7);
.dialog-content {
position: relative;
box-sizing: border-box;
// padding: 16px;
margin: 0 auto;
overflow-wrap: break-word;
background: #333333;
border-radius: 2px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
.dialog-header {
display: flex;
align-items: center;
justify-content: space-between;
height: 31.65rpx;
padding: 9.38rpx 0 9.77rpx 0;
color: #ffffff;
background: #fff;
border-bottom: 0.39rpx solid #dadde6;
}
.mes-dialog-layout-main {
box-sizing: border-box;
flex: 1;
padding: 16px;
// color: #ffffff;
background: #fff;
}
.dialog-btn {
display: flex;
justify-content: flex-end;
padding: 10px;
background: #fff;
.dialog-button-cancel,
.dialog-button-confirm {
box-sizing: border-box;
display: inline-flex;
align-items: center;
justify-content: center;
height: 32px;
padding: 8px 15px;
margin-left: 10px;
font-size: 14px;
font-weight: 500;
line-height: 1;
color: #fff;
text-align: center;
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
-webkit-user-select: none;
user-select: none;
background-color: #2478f2;
border: 1px solid #dcdfe6;
border-color: #2478f2;
border-radius: 4px;
outline: 0;
transition: 0.1s;
}
}
}
}
</style>
<style>
.dialog-fade-enter-active,
.dialog-fade-leave-active {
transition: opacity 0.3s ease;
}
.dialog-fade-enter,
.dialog-fade-leave-to {
opacity: 0;
}
</style>
使用:
<ssDialog
v-model="showDialog"
width="664.06rpx"
height="312.5rpx"
top="54.69rpx"
title="开心"
:showCancel="false"
:showConfirm="false"
closeOnClickModal
@before-close="dialogBeforeClose"
>
<managementList />
</ssDialog>