auth-web/src/components/BaseDialog/index.vue

155 lines
4.7 KiB
Vue

<script lang="ts" setup>
import { type ButtonProps, closeDialog, type DialogOptions, dialogStore, type EventType } from './index';
import { computed, ref } from 'vue';
import { isFunction } from '@pureadmin/utils';
import Fullscreen from '@iconify-icons/ri/fullscreen-fill';
import ExitFullscreen from '@iconify-icons/ri/fullscreen-exit-fill';
import { $t } from '@/plugins/i18n';
defineOptions({
name: 'ReDialog',
});
const sureBtnMap = ref({});
const fullscreen = ref(false);
const footerButtons = computed(() => {
return (options: DialogOptions) => {
return options?.footerButtons?.length > 0
? options.footerButtons
: ([
{
label: $t('cancel'),
text: true,
bg: true,
btnClick: ({ dialog: { options, index } }) => {
const done = () => closeDialog(options, index, { command: 'cancel' });
if (options?.beforeCancel && isFunction(options?.beforeCancel)) {
options.beforeCancel(done, { options, index });
} else {
done();
}
},
},
{
label: $t('confirm'),
type: 'primary',
text: true,
bg: true,
popconfirm: options?.popconfirm,
btnClick: ({ dialog: { options, index } }) => {
if (options?.sureBtnLoading) {
sureBtnMap.value[index] = Object.assign({}, sureBtnMap.value[index], {
loading: true,
});
}
const closeLoading = () => {
if (options?.sureBtnLoading) {
sureBtnMap.value[index].loading = false;
}
};
const done = () => {
closeLoading();
closeDialog(options, index, { command: 'sure' });
};
if (options?.beforeSure && isFunction(options?.beforeSure)) {
options.beforeSure(done, { options, index, closeLoading });
} else {
done();
}
},
},
] as Array<ButtonProps>);
};
});
const fullscreenClass = computed(() => {
return ['el-icon', 'el-dialog__close', '-translate-x-2', 'cursor-pointer', 'hover:!text-[red]'];
});
function eventsCallBack(event: EventType, options: DialogOptions, index: number, isClickFullScreen = false) {
if (!isClickFullScreen) fullscreen.value = options?.fullscreen ?? false;
if (options?.[event] && isFunction(options?.[event])) {
return options?.[event]({ options, index });
}
}
function handleClose(options: DialogOptions, index: number, args = { command: 'close' }) {
closeDialog(options, index, args);
eventsCallBack('close', options, index);
}
</script>
<template>
<el-dialog
v-for="(options, index) in dialogStore"
:key="index"
v-model="options.visible"
:fullscreen="fullscreen ? true : !!options?.fullscreen"
class="pure-dialog"
v-bind="options"
@closeAutoFocus="eventsCallBack('closeAutoFocus', options, index)"
@closed="handleClose(options, index)"
@openAutoFocus="eventsCallBack('openAutoFocus', options, index)"
@opened="eventsCallBack('open', options, index)"
>
<!-- header -->
<template v-if="options?.fullscreenIcon || options?.headerRenderer" #header="{ close, titleId, titleClass }">
<div v-if="options?.fullscreenIcon" class="flex items-center justify-between">
<span :id="titleId" :class="titleClass">{{ options?.title }}</span>
<i
v-if="!options?.fullscreen"
:class="fullscreenClass"
@click="
() => {
fullscreen = !fullscreen;
eventsCallBack('fullscreenCallBack', { ...options, fullscreen }, index, true);
}
"
>
<IconifyIconOffline :icon="options?.fullscreen ? ExitFullscreen : fullscreen ? ExitFullscreen : Fullscreen" class="pure-dialog-svg" />
</i>
</div>
<component :is="options?.headerRenderer({ close, titleId, titleClass })" v-else />
</template>
<component :is="options.contentRenderer({ options, index })" v-bind="options?.props" @close="args => handleClose(options, index, args)" />
<!-- footer -->
<template v-if="!options?.hideFooter" #footer>
<template v-if="options?.footerRenderer">
<component :is="options?.footerRenderer({ options, index })" />
</template>
<span v-else>
<template v-for="(btn, key) in footerButtons(options)" :key="key">
<el-popconfirm
v-if="btn.popconfirm"
v-bind="btn.popconfirm"
@confirm="
btn.btnClick({
dialog: { options, index },
button: { btn, index: key },
})
"
>
<template #reference>
<el-button v-bind="btn">{{ btn?.label }}</el-button>
</template>
</el-popconfirm>
<el-button
v-else
:loading="key === 1 && sureBtnMap[index]?.loading"
v-bind="btn"
@click="
btn.btnClick({
dialog: { options, index },
button: { btn, index: key },
})
"
>
{{ btn?.label }}
</el-button>
</template>
</span>
</template>
</el-dialog>
</template>