mirror of
https://github.com/fantastic-admin/basic.git
synced 2026-10-07 14:57:52 +08:00
FaModal 组件增加 beforeClose 回调函数,优化关闭逻辑并支持异步处理
This commit is contained in:
@@ -22,6 +22,10 @@ export interface ModalProps {
|
||||
cancelButtonText?: string
|
||||
confirmButtonDisabled?: boolean
|
||||
confirmButtonLoading?: boolean
|
||||
beforeClose?: (
|
||||
action: 'confirm' | 'cancel' | 'close',
|
||||
done: () => void
|
||||
) => void
|
||||
header?: boolean
|
||||
footer?: boolean
|
||||
closeOnClickOverlay?: boolean
|
||||
@@ -30,7 +34,6 @@ export interface ModalProps {
|
||||
headerClass?: HTMLAttributes['class']
|
||||
contentClass?: HTMLAttributes['class']
|
||||
footerClass?: HTMLAttributes['class']
|
||||
modalId?: string
|
||||
}
|
||||
export interface ModalEmits {
|
||||
'update:modelValue': [value: boolean]
|
||||
@@ -44,13 +47,13 @@ export interface ModalEmits {
|
||||
|
||||
type alertOptions = Pick<ModalProps, 'title' | 'description' | 'icon' | 'alignCenter' | 'overlay' | 'overlayBlur' | 'confirmButtonText' | 'confirmButtonDisabled' | 'confirmButtonLoading' | 'closeOnClickOverlay' | 'closeOnPressEscape' | 'class' | 'headerClass' | 'contentClass' | 'footerClass'> & {
|
||||
content: string
|
||||
onConfirm?: () => any
|
||||
onConfirm?: () => void
|
||||
}
|
||||
|
||||
type confirmOptions = Pick<ModalProps, 'title' | 'description' | 'alignCenter' | 'overlay' | 'overlayBlur' | 'confirmButtonText' | 'cancelButtonText' | 'confirmButtonDisabled' | 'confirmButtonLoading' | 'closeOnClickOverlay' | 'closeOnPressEscape' | 'class' | 'headerClass' | 'contentClass' | 'footerClass'> & {
|
||||
type confirmOptions = Pick<ModalProps, 'title' | 'description' | 'alignCenter' | 'overlay' | 'overlayBlur' | 'confirmButtonText' | 'cancelButtonText' | 'confirmButtonDisabled' | 'confirmButtonLoading' | 'beforeClose' | 'closeOnClickOverlay' | 'closeOnPressEscape' | 'class' | 'headerClass' | 'contentClass' | 'footerClass'> & {
|
||||
content: string
|
||||
onConfirm?: () => any
|
||||
onCancel?: () => any
|
||||
onConfirm?: () => void
|
||||
onCancel?: () => void
|
||||
}
|
||||
|
||||
export function useFaModal() {
|
||||
@@ -67,7 +70,6 @@ export function useFaModal() {
|
||||
closeOnClickOverlay: false,
|
||||
contentClass: 'py-0 min-h-auto',
|
||||
footerClass: 'p-4',
|
||||
modalId: useId(),
|
||||
onClosed: () => {
|
||||
app.unmount()
|
||||
},
|
||||
@@ -89,7 +91,6 @@ export function useFaModal() {
|
||||
closeOnClickOverlay: false,
|
||||
contentClass: 'py-0 min-h-auto',
|
||||
footerClass: 'p-4',
|
||||
modalId: useId(),
|
||||
onClosed: () => {
|
||||
app.unmount()
|
||||
},
|
||||
@@ -111,7 +112,6 @@ export function useFaModal() {
|
||||
closeOnClickOverlay: false,
|
||||
contentClass: 'py-0 min-h-auto',
|
||||
footerClass: 'p-4',
|
||||
modalId: useId(),
|
||||
onClosed: () => {
|
||||
app.unmount()
|
||||
},
|
||||
@@ -133,7 +133,6 @@ export function useFaModal() {
|
||||
closeOnClickOverlay: false,
|
||||
contentClass: 'py-0 min-h-auto',
|
||||
footerClass: 'p-4',
|
||||
modalId: useId(),
|
||||
onClosed: () => {
|
||||
app.unmount()
|
||||
},
|
||||
@@ -155,7 +154,6 @@ export function useFaModal() {
|
||||
contentClass: 'py-0 min-h-auto',
|
||||
footerClass: 'p-4',
|
||||
showCancelButton: true,
|
||||
modalId: useId(),
|
||||
onClosed: () => {
|
||||
app.unmount()
|
||||
},
|
||||
|
||||
@@ -83,6 +83,7 @@ function setTransform() {
|
||||
}
|
||||
|
||||
watch(isOpen, (val) => {
|
||||
emits('update:modelValue', val)
|
||||
if (val) {
|
||||
nextTick(() => {
|
||||
if (dialogContentRef.value) {
|
||||
@@ -90,28 +91,69 @@ watch(isOpen, (val) => {
|
||||
setTransform()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
function updateOpen(value: boolean) {
|
||||
isOpen.value = value
|
||||
emits('update:modelValue', value)
|
||||
if (value) {
|
||||
emits('open')
|
||||
}
|
||||
else {
|
||||
emits('close')
|
||||
}
|
||||
})
|
||||
|
||||
async function updateOpen(value: boolean) {
|
||||
if (value) {
|
||||
isOpen.value = value
|
||||
emits('open')
|
||||
}
|
||||
else {
|
||||
if (props.beforeClose) {
|
||||
await props.beforeClose(
|
||||
'close',
|
||||
() => {
|
||||
isOpen.value = value
|
||||
emits('close')
|
||||
},
|
||||
)
|
||||
}
|
||||
else {
|
||||
isOpen.value = value
|
||||
emits('close')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onConfirm() {
|
||||
updateOpen(false)
|
||||
emits('confirm')
|
||||
const isConfirmButtonLoading = ref(false)
|
||||
|
||||
async function onConfirm() {
|
||||
if (props.beforeClose) {
|
||||
isConfirmButtonLoading.value = true
|
||||
await props.beforeClose(
|
||||
'confirm',
|
||||
() => {
|
||||
isOpen.value = false
|
||||
emits('confirm')
|
||||
},
|
||||
)
|
||||
isConfirmButtonLoading.value = false
|
||||
}
|
||||
else {
|
||||
isOpen.value = false
|
||||
emits('confirm')
|
||||
}
|
||||
}
|
||||
|
||||
function onCancel() {
|
||||
updateOpen(false)
|
||||
emits('cancel')
|
||||
async function onCancel() {
|
||||
if (props.beforeClose) {
|
||||
await props.beforeClose(
|
||||
'cancel',
|
||||
() => {
|
||||
isOpen.value = false
|
||||
emits('cancel')
|
||||
},
|
||||
)
|
||||
}
|
||||
else {
|
||||
isOpen.value = false
|
||||
emits('cancel')
|
||||
}
|
||||
}
|
||||
|
||||
function handleFocusOutside(e: Event) {
|
||||
@@ -223,7 +265,7 @@ function handleAnimationEnd() {
|
||||
<FaButton v-if="showCancelButton" variant="outline" @click="onCancel">
|
||||
{{ cancelButtonText }}
|
||||
</FaButton>
|
||||
<FaButton v-if="showConfirmButton" :disabled="confirmButtonDisabled" :loading="confirmButtonLoading" @click="onConfirm">
|
||||
<FaButton v-if="showConfirmButton" :disabled="confirmButtonDisabled" :loading="confirmButtonLoading || isConfirmButtonLoading" @click="onConfirm">
|
||||
{{ confirmButtonText }}
|
||||
</FaButton>
|
||||
</slot>
|
||||
|
||||
@@ -4,6 +4,7 @@ meta:
|
||||
</route>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { toast } from 'vue-sonner'
|
||||
import { useFaModal } from '@/ui/components/FaModal'
|
||||
|
||||
const modal = ref(false)
|
||||
@@ -25,34 +26,87 @@ watch(() => modalInfo.value.loading, (loading) => {
|
||||
}
|
||||
})
|
||||
|
||||
function handleBeforeClose(action: 'confirm' | 'cancel' | 'close', done: () => void) {
|
||||
if (action === 'close') {
|
||||
useFaModal().confirm({
|
||||
title: '提示',
|
||||
content: '确定要关闭吗?',
|
||||
onConfirm: () => {
|
||||
done()
|
||||
},
|
||||
})
|
||||
}
|
||||
else {
|
||||
done()
|
||||
}
|
||||
}
|
||||
|
||||
function showModalInfo() {
|
||||
useFaModal().info({
|
||||
title: '温馨提醒',
|
||||
content: '这是 info 弹窗',
|
||||
onConfirm: () => {
|
||||
toast.info('你点了确定')
|
||||
},
|
||||
})
|
||||
}
|
||||
function showModalSuccess() {
|
||||
useFaModal().success({
|
||||
title: '温馨提醒',
|
||||
content: '这是 success 弹窗',
|
||||
onConfirm: () => {
|
||||
toast.success('你点了确定')
|
||||
},
|
||||
})
|
||||
}
|
||||
function showModalWarning() {
|
||||
useFaModal().warning({
|
||||
title: '温馨提醒',
|
||||
content: '这是 warning 弹窗',
|
||||
onConfirm: () => {
|
||||
toast.warning('你点了确定')
|
||||
},
|
||||
})
|
||||
}
|
||||
function showModalError() {
|
||||
useFaModal().error({
|
||||
title: '温馨提醒',
|
||||
content: '这是 confirm 弹窗',
|
||||
onConfirm: () => {
|
||||
toast.error('你点了确定')
|
||||
},
|
||||
})
|
||||
}
|
||||
function showModalConfirm() {
|
||||
useFaModal().confirm({
|
||||
title: '温馨提醒',
|
||||
content: '这是 confirm 弹窗',
|
||||
onConfirm: () => {
|
||||
toast.success('你点了确定')
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function showModalPromiseConfirm() {
|
||||
useFaModal().confirm({
|
||||
title: '温馨提醒',
|
||||
content: '这是 confirm 弹窗',
|
||||
confirmButtonText: '确认(随机成功或失败)',
|
||||
beforeClose: async (action, done) => {
|
||||
if (action === 'confirm') {
|
||||
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||
if (Math.random() > 0.5) {
|
||||
toast.success('成功了!')
|
||||
done()
|
||||
}
|
||||
else {
|
||||
toast.error('失败了!')
|
||||
}
|
||||
}
|
||||
else {
|
||||
done()
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@@ -80,8 +134,11 @@ function showModalConfirm() {
|
||||
<FaButton @click="showModalConfirm">
|
||||
Confirm
|
||||
</FaButton>
|
||||
<FaButton @click="showModalPromiseConfirm">
|
||||
Confirm with promise
|
||||
</FaButton>
|
||||
</div>
|
||||
<FaModal v-model="modal" title="标题" description="这里是一段描述介绍" :maximizable="modalInfo.maximizable" :closable="modalInfo.closable" :draggable="modalInfo.draggable" :center="modalInfo.center" :loading="modalInfo.loading" :header="modalInfo.header" :footer="modalInfo.footer">
|
||||
<FaModal v-model="modal" title="标题" description="这里是一段描述介绍" :maximizable="modalInfo.maximizable" :closable="modalInfo.closable" :draggable="modalInfo.draggable" :center="modalInfo.center" :loading="modalInfo.loading" :header="modalInfo.header" :footer="modalInfo.footer" :before-close="handleBeforeClose">
|
||||
<div :class="modalInfo.contentHeight">
|
||||
<div class="flex-start-center flex-wrap gap-2">
|
||||
<FaButton :variant="modalInfo.maximizable ? 'default' : 'outline'" class="w-full" @click="modalInfo.maximizable = !modalInfo.maximizable">
|
||||
|
||||
Reference in New Issue
Block a user