фикс
This commit is contained in:
parent
4ef4c5f428
commit
71b48b5d25
34
src/App.vue
34
src/App.vue
@ -63,6 +63,18 @@
|
|||||||
</router-link>
|
</router-link>
|
||||||
</template>
|
</template>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
<!-- Контейнер для уведомлений -->
|
||||||
|
<div class="toast-list">
|
||||||
|
<Toast
|
||||||
|
v-for="toast in toasts"
|
||||||
|
:key="toast.id"
|
||||||
|
:message="toast.message"
|
||||||
|
:type="toast.type"
|
||||||
|
:duration="toast.duration"
|
||||||
|
@close="removeToast(toast.id)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -72,10 +84,16 @@ import { ref, watch, onMounted, computed, onUnmounted } from 'vue';
|
|||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import api from '@/services/api';
|
import api from '@/services/api';
|
||||||
import { getSocket, connectSocket } from '@/services/socketService';
|
import { getSocket, connectSocket } from '@/services/socketService';
|
||||||
|
import Toast from '@/components/Toast.vue';
|
||||||
|
import toastService from '@/services/toastService';
|
||||||
|
|
||||||
const { user, isAuthenticated, logout, fetchUser } = useAuth();
|
const { user, isAuthenticated, logout, fetchUser } = useAuth();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
|
// Импортируем уведомления из сервиса
|
||||||
|
const toasts = toastService.toasts;
|
||||||
|
const removeToast = toastService.remove;
|
||||||
|
|
||||||
const userData = ref(null);
|
const userData = ref(null);
|
||||||
const authState = ref(false);
|
const authState = ref(false);
|
||||||
const conversations = ref([]);
|
const conversations = ref([]);
|
||||||
@ -270,6 +288,22 @@ body {
|
|||||||
will-change: transform; /* Ускорение для анимаций */
|
will-change: transform; /* Ускорение для анимаций */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Контейнер для уведомлений */
|
||||||
|
.toast-list {
|
||||||
|
position: fixed;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
z-index: 2000;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toast-list > * {
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
#app-container {
|
#app-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
117
src/components/Toast.vue
Normal file
117
src/components/Toast.vue
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
<template>
|
||||||
|
<transition name="toast-fade">
|
||||||
|
<div v-if="show" class="toast-container" :class="type">
|
||||||
|
<div class="toast-content">
|
||||||
|
<i v-if="type === 'success'" class="bi-check-circle-fill"></i>
|
||||||
|
<i v-else-if="type === 'error'" class="bi-exclamation-circle-fill"></i>
|
||||||
|
<i v-else-if="type === 'warning'" class="bi-exclamation-triangle-fill"></i>
|
||||||
|
<i v-else class="bi-info-circle-fill"></i>
|
||||||
|
<span>{{ message }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ref, onMounted, onBeforeUnmount } from 'vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Toast',
|
||||||
|
props: {
|
||||||
|
message: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
duration: {
|
||||||
|
type: Number,
|
||||||
|
default: 3000
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: 'info',
|
||||||
|
validator(value) {
|
||||||
|
return ['info', 'success', 'warning', 'error'].includes(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emits: ['close'],
|
||||||
|
setup(props, { emit }) {
|
||||||
|
const show = ref(false);
|
||||||
|
let timer = null;
|
||||||
|
|
||||||
|
const startTimer = () => {
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
show.value = false;
|
||||||
|
setTimeout(() => emit('close'), 300); // Даем время для завершения анимации
|
||||||
|
}, props.duration);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
show.value = true;
|
||||||
|
startTimer();
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
show
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.toast-container {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 20px;
|
||||||
|
right: 20px;
|
||||||
|
padding: 12px 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
color: white;
|
||||||
|
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
|
||||||
|
z-index: 1000;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
max-width: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toast-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toast-content i {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success {
|
||||||
|
background-color: #4caf50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
background-color: #2196f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning {
|
||||||
|
background-color: #ff9800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
background-color: #f44336;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Анимация появления и исчезновения */
|
||||||
|
.toast-fade-enter-active,
|
||||||
|
.toast-fade-leave-active {
|
||||||
|
transition: opacity 0.3s, transform 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toast-fade-enter-from,
|
||||||
|
.toast-fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
}
|
||||||
|
</style>
|
48
src/services/toastService.js
Normal file
48
src/services/toastService.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// Простой сервис для отображения всплывающих уведомлений
|
||||||
|
import { ref, reactive } from 'vue';
|
||||||
|
|
||||||
|
const toasts = reactive([]);
|
||||||
|
let toastId = 0;
|
||||||
|
|
||||||
|
// Добавление нового уведомления
|
||||||
|
const add = (message, type = 'info', duration = 3000) => {
|
||||||
|
const id = toastId++;
|
||||||
|
toasts.push({ id, message, type, duration });
|
||||||
|
|
||||||
|
// Автоматически убираем уведомление через duration + 300ms анимации
|
||||||
|
setTimeout(() => {
|
||||||
|
remove(id);
|
||||||
|
}, duration + 300);
|
||||||
|
|
||||||
|
return id;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Удаление уведомления по ID
|
||||||
|
const remove = (id) => {
|
||||||
|
const index = toasts.findIndex(toast => toast.id === id);
|
||||||
|
if (index > -1) {
|
||||||
|
toasts.splice(index, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Показ информационного уведомления
|
||||||
|
const info = (message, duration) => add(message, 'info', duration);
|
||||||
|
|
||||||
|
// Показ уведомления об успехе
|
||||||
|
const success = (message, duration) => add(message, 'success', duration);
|
||||||
|
|
||||||
|
// Показ предупреждения
|
||||||
|
const warning = (message, duration) => add(message, 'warning', duration);
|
||||||
|
|
||||||
|
// Показ уведомления об ошибке
|
||||||
|
const error = (message, duration) => add(message, 'error', duration);
|
||||||
|
|
||||||
|
export default {
|
||||||
|
toasts,
|
||||||
|
add,
|
||||||
|
remove,
|
||||||
|
info,
|
||||||
|
success,
|
||||||
|
warning,
|
||||||
|
error
|
||||||
|
};
|
@ -142,6 +142,7 @@
|
|||||||
import { ref, onMounted, computed } from 'vue';
|
import { ref, onMounted, computed } from 'vue';
|
||||||
import { useRouter, useRoute } from 'vue-router';
|
import { useRouter, useRoute } from 'vue-router';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import toastService from '@/services/toastService';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AdminUserDetail',
|
name: 'AdminUserDetail',
|
||||||
@ -214,11 +215,12 @@ export default {
|
|||||||
// Обновляем статус пользователя
|
// Обновляем статус пользователя
|
||||||
user.value.isActive = response.data.isActive;
|
user.value.isActive = response.data.isActive;
|
||||||
|
|
||||||
// Показываем уведомление (можно добавить компонент уведомлений)
|
// Заменяем alert на уведомление через сервис
|
||||||
alert(response.data.message);
|
const actionType = user.value.isActive ? 'success' : 'warning';
|
||||||
|
toastService.add(response.data.message, actionType, 3000);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Ошибка при изменении статуса пользователя:', err);
|
console.error('Ошибка при изменении статуса пользователя:', err);
|
||||||
alert('Ошибка при изменении статуса пользователя');
|
toastService.error('Ошибка при изменении статуса пользователя');
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
@ -167,6 +167,7 @@
|
|||||||
import { ref, onMounted } from 'vue';
|
import { ref, onMounted } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import toastService from '@/services/toastService';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AdminUsers',
|
name: 'AdminUsers',
|
||||||
@ -270,11 +271,12 @@ export default {
|
|||||||
users.value[userIndex].isActive = response.data.isActive;
|
users.value[userIndex].isActive = response.data.isActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Показываем уведомление (можно добавить компонент уведомлений)
|
// Заменяем стандартный alert на наш сервис уведомлений
|
||||||
alert(response.data.message);
|
const type = response.data.isActive ? 'success' : 'warning';
|
||||||
|
toastService.add(response.data.message, type, 3000);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Ошибка при изменении статуса пользователя:', err);
|
console.error('Ошибка при изменении статуса пользователя:', err);
|
||||||
alert('Ошибка при изменении статуса пользователя');
|
toastService.error('Ошибка при изменении статуса пользователя');
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user