91 lines
3.6 KiB
Plaintext
91 lines
3.6 KiB
Plaintext
---
|
||
description: Правило реализации диалогов подтверждения для действий
|
||
alwaysApply: false
|
||
---
|
||
## Правило реализации диалогов подтверждения
|
||
|
||
### Принцип
|
||
Диалоги подтверждения должны реализовываться в UI компонентах кнопок, а не в composables функций моделей. Composable отвечает только за бизнес-логику выполнения действия.
|
||
|
||
### Структура реализации
|
||
|
||
```vue
|
||
<template lang="pug">
|
||
q-btn(
|
||
@click='showDialog = true',
|
||
:loading='isSubmitting'
|
||
)
|
||
// иконка действия
|
||
|
||
q-dialog(v-model='showDialog', @hide='close')
|
||
ModalBase(title='Заголовок действия')
|
||
Form.q-pa-sm(
|
||
:handler-submit='handleAction',
|
||
:is-submitting='isSubmitting',
|
||
:button-cancel-txt='"Отменить"',
|
||
:button-submit-txt='"Выполнить"',
|
||
@cancel='close'
|
||
)
|
||
div(style='max-width: 400px')
|
||
p Подтверждающее сообщение
|
||
// дополнительные поля ввода если нужны
|
||
</template>
|
||
|
||
<script lang="ts" setup>
|
||
// Импорты
|
||
import { FailAlert, SuccessAlert } from 'src/shared/api';
|
||
import { useModelFunction } from '../model';
|
||
import { ref } from 'vue';
|
||
import { ModalBase } from 'src/shared/ui/ModalBase';
|
||
import { Form } from 'src/shared/ui/Form';
|
||
|
||
// Props, emits
|
||
const emit = defineEmits(['actionCompleted', 'close']);
|
||
|
||
// Состояние
|
||
const { actionFunction } = useModelFunction();
|
||
const isSubmitting = ref(false);
|
||
const showDialog = ref(false);
|
||
|
||
// Важно: composable useModelFunction НЕ содержит try-catch!
|
||
// Он просто выполняет действие и возвращает результат.
|
||
// Вся обработка ошибок происходит здесь, в UI компоненте.
|
||
|
||
// Функции
|
||
const close = () => {
|
||
showDialog.value = false;
|
||
emit('close');
|
||
};
|
||
|
||
const handleAction = async () => {
|
||
isSubmitting.value = true;
|
||
try {
|
||
await actionFunction(params);
|
||
SuccessAlert('Действие выполнено');
|
||
emit('actionCompleted');
|
||
close();
|
||
} catch (e: any) {
|
||
FailAlert(`Возникла ошибка: ${e.message}`);
|
||
close();
|
||
} finally {
|
||
isSubmitting.value = false;
|
||
}
|
||
};
|
||
</script>
|
||
```
|
||
|
||
### Ключевые моменты
|
||
- **Диалог в компоненте**: Не в composable, а в UI компоненте
|
||
- **Состояние в компоненте**: `showDialog`, `isSubmitting` управляются локально
|
||
- **Эмиссия событий**: Для внешней обработки результатов действия
|
||
- **Composable без try-catch**: Функции модели НЕ содержат обработку ошибок, только выполнение действия
|
||
- **Уведомления**: Использовать `FailAlert`/`SuccessAlert` вместо прямых вызовов Notify
|
||
- **Валидация**: Проверять данные перед отправкой в composable
|
||
- **Очистка состояния**: Сбрасывать поля при закрытии диалога
|
||
- **Нет window.location.reload()**: Обновление данных через store или emits
|
||
|
||
### Примеры применения
|
||
- Удаление объектов (DeleteStoryButton.vue)
|
||
- Подтверждение действий (ConfirmApprovalButton.vue)
|
||
- Отклонение с причиной (DeclineApprovalButton.vue)
|