63 lines
1.6 KiB
Vue
63 lines
1.6 KiB
Vue
<template>
|
||
<el-dialog v-model="visible" :title="title" width="400px">
|
||
<p>{{ content }}</p>
|
||
<template #footer>
|
||
<el-button @click="visible = false">取消</el-button>
|
||
<el-button type="danger" @click="handleConfirm" :loading="loading">{{ confirmText }}</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, watch } from 'vue'
|
||
|
||
const props = defineProps({
|
||
modelValue: Boolean,
|
||
title: {
|
||
type: String,
|
||
default: '确认删除'
|
||
},
|
||
confirmText: {
|
||
type: String,
|
||
default: '确认删除'
|
||
},
|
||
content: {
|
||
type: String,
|
||
default: '确定要删除此数据吗?此操作不可恢复。'
|
||
},
|
||
// 确认后执行的实际操作,由父组件传入并返回 Promise。
|
||
// 这里刻意不用 emit('confirm'):emit 是同步的,拿不到父组件异步操作的结果,
|
||
// 会退化成"请求刚发出去弹窗就关了",失败时用户得把确认流程重走一遍。
|
||
onConfirm: {
|
||
type: Function,
|
||
required: true
|
||
}
|
||
})
|
||
|
||
const emit = defineEmits(['update:modelValue'])
|
||
|
||
const visible = ref(props.modelValue)
|
||
const loading = ref(false)
|
||
|
||
watch(() => props.modelValue, (val) => {
|
||
visible.value = val
|
||
})
|
||
|
||
watch(visible, (val) => {
|
||
emit('update:modelValue', val)
|
||
})
|
||
|
||
async function handleConfirm() {
|
||
loading.value = true
|
||
try {
|
||
await props.onConfirm()
|
||
// 只有父组件的操作成功返回才关闭弹窗:失败时留着,用户可以直接再点一次
|
||
visible.value = false
|
||
} catch (e) {
|
||
// 失败原因已由 axios 拦截器统一提示,这里只负责别把弹窗关掉
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
</script>
|