first commit
This commit is contained in:
86
resources/js/components/AppDialog.vue
Normal file
86
resources/js/components/AppDialog.vue
Normal file
@@ -0,0 +1,86 @@
|
||||
<script setup lang="ts">
|
||||
import { NButton, NFlex, NModal, NSpace, NSpin, NText } from 'naive-ui';
|
||||
import type { AppDialogButtonProps } from '../composables/useAppDialog';
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
show: boolean;
|
||||
loading?: boolean;
|
||||
title?: string;
|
||||
content?: string;
|
||||
positiveText?: string;
|
||||
negativeText?: string;
|
||||
maskClosable?: boolean;
|
||||
positiveProps?: AppDialogButtonProps;
|
||||
negativeProps?: AppDialogButtonProps;
|
||||
}>(),
|
||||
{
|
||||
loading: false,
|
||||
positiveText: 'Подтвердить',
|
||||
negativeText: 'Отмена',
|
||||
maskClosable: false,
|
||||
positiveProps: () => ({ type: 'error', secondary: true }),
|
||||
negativeProps: () => ({ type: 'primary', secondary: true }),
|
||||
},
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:show': [value: boolean];
|
||||
confirm: [];
|
||||
cancel: [];
|
||||
'after-leave': [];
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NModal
|
||||
:show="show"
|
||||
:mask-closable="maskClosable"
|
||||
preset="card"
|
||||
class="relative max-w-sm overflow-clip"
|
||||
:title="title"
|
||||
@update:show="(val) => emit('update:show', val)"
|
||||
@after-leave="emit('after-leave')"
|
||||
>
|
||||
<NFlex vertical size="large">
|
||||
<NSpace vertical :size="0">
|
||||
<NText v-if="content" tag="p">{{ content }}</NText>
|
||||
</NSpace>
|
||||
|
||||
<NSpace vertical size="small">
|
||||
<NButton
|
||||
v-if="negativeText"
|
||||
block
|
||||
v-bind="negativeProps"
|
||||
@click="emit('cancel')"
|
||||
>
|
||||
{{ negativeText }}
|
||||
</NButton>
|
||||
<NButton
|
||||
v-if="positiveText"
|
||||
block
|
||||
v-bind="positiveProps"
|
||||
@click="emit('confirm')"
|
||||
>
|
||||
{{ positiveText }}
|
||||
</NButton>
|
||||
</NSpace>
|
||||
</NFlex>
|
||||
|
||||
<div
|
||||
v-if="loading"
|
||||
class="absolute inset-0"
|
||||
style="
|
||||
background-color: color-mix(
|
||||
in srgb,
|
||||
var(--n-color-embedded-modal),
|
||||
transparent 50%
|
||||
);
|
||||
"
|
||||
>
|
||||
<div class="flex h-full flex-col items-center justify-center">
|
||||
<NSpin description="Загрузка" />
|
||||
</div>
|
||||
</div>
|
||||
</NModal>
|
||||
</template>
|
||||
53
resources/js/components/AppDialogManager.vue
Normal file
53
resources/js/components/AppDialogManager.vue
Normal file
@@ -0,0 +1,53 @@
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
cleanupDialog,
|
||||
closeDialog,
|
||||
dialogQueue
|
||||
|
||||
} from '../composables/useAppDialog';
|
||||
import type {AppDialogItem} from '../composables/useAppDialog';
|
||||
import AppDialog from './AppDialog.vue';
|
||||
|
||||
const handleConfirm = async (dialog: AppDialogItem): Promise<void> => {
|
||||
dialog.loading = true;
|
||||
|
||||
try {
|
||||
if (typeof dialog.onConfirm === 'function') {
|
||||
await dialog.onConfirm();
|
||||
}
|
||||
|
||||
closeDialog(dialog.id, true);
|
||||
} catch (error) {
|
||||
console.error('Ошибка при подтверждении диалога:', error);
|
||||
dialog.loading = false; // Оставляем диалог открытым при ошибке.
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Teleport to="body">
|
||||
<AppDialog
|
||||
v-for="dialog in dialogQueue"
|
||||
:key="dialog.id"
|
||||
:show="dialog.show"
|
||||
:loading="dialog.loading"
|
||||
:title="dialog.title"
|
||||
:content="dialog.content"
|
||||
:positive-text="dialog.positiveText"
|
||||
:negative-text="dialog.negativeText"
|
||||
:positive-props="dialog.positiveProps"
|
||||
:negative-props="dialog.negativeProps"
|
||||
:mask-closable="dialog.maskClosable"
|
||||
@confirm="handleConfirm(dialog)"
|
||||
@cancel="closeDialog(dialog.id, false)"
|
||||
@update:show="
|
||||
(val) =>
|
||||
!val &&
|
||||
dialog.show &&
|
||||
!dialog.loading &&
|
||||
closeDialog(dialog.id, false)
|
||||
"
|
||||
@after-leave="cleanupDialog(dialog.id)"
|
||||
/>
|
||||
</Teleport>
|
||||
</template>
|
||||
15
resources/js/components/Noise.vue
Normal file
15
resources/js/components/Noise.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
withDefaults(defineProps<{ opacity?: number }>(), {
|
||||
opacity: 0.014,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="pointer-events-none fixed inset-0 z-[9999] size-full"
|
||||
:style="{
|
||||
backgroundImage: 'url(/assets/noise.png)',
|
||||
opacity,
|
||||
}"
|
||||
/>
|
||||
</template>
|
||||
Reference in New Issue
Block a user