diff --git a/src/auth.js b/src/auth.js index e304721..cad8b1e 100644 --- a/src/auth.js +++ b/src/auth.js @@ -129,6 +129,8 @@ async function logout() { // Функция обработки события блокировки аккаунта function handleAccountBlocked(data) { + console.log('Обработка блокировки аккаунта:', data); + // Создаем объект с информацией о блокировке const blockInfo = { blocked: true, @@ -140,10 +142,16 @@ function handleAccountBlocked(data) { // Сохраняем информацию о блокировке в localStorage для отображения на странице логина localStorage.setItem('accountBlockedInfo', JSON.stringify(blockInfo)); - // Выполняем выход пользователя + // Немедленно выполняем выход пользователя - сначала очищаем данные user.value = null; token.value = null; localStorage.removeItem('userToken'); + + // Удаляем токен из заголовков для будущих запросов API + api.setAuthToken(null); + + // Принудительно прерываем все активные запросы API, если они есть + api.cancelActiveRequests && api.cancelActiveRequests(); // Перенаправляем на страницу входа с уведомлением о блокировке router.push({ diff --git a/src/services/api.js b/src/services/api.js index 971e240..930e654 100644 --- a/src/services/api.js +++ b/src/services/api.js @@ -4,6 +4,9 @@ import { useAuth } from '../auth'; // Импортируем функцию ав // Создаем экземпляр Axios с базовым URL нашего API // Настраиваем базовый URL в зависимости от окружения +// Храним токены отмены запросов для возможности отмены при блокировке +const cancelTokenSources = new Map(); + // Определяем базовый URL в зависимости от среды выполнения const getBaseUrl = () => { // Всегда используем относительный путь /api. @@ -30,6 +33,20 @@ apiClient.interceptors.request.use( } else { console.log('[API] Токен не найден для запроса:', config.url); } + + // Добавляем CancelToken к запросу для возможности отмены + const source = axios.CancelToken.source(); + config.cancelToken = source.token; + + // Сохраняем источник токена отмены в Map по URL запроса как ключу + const requestKey = `${config.method}-${config.url}`; + cancelTokenSources.set(requestKey, source); + + // Добавляем обработчик, который удаляет источник токена отмены после завершения запроса + config.onFinally = () => { + cancelTokenSources.delete(requestKey); + }; + return config; }, (error) => { @@ -40,8 +57,19 @@ apiClient.interceptors.request.use( // (Опционально) Перехватчик ответов для обработки глобальных ошибок, например, 401 apiClient.interceptors.response.use( - (response) => response, + (response) => { + // Удаляем источник токена отмены после успешного ответа + const requestKey = `${response.config.method}-${response.config.url}`; + cancelTokenSources.delete(requestKey); + return response; + }, (error) => { + // Удаляем источник токена отмены при ошибке + if (error.config) { + const requestKey = `${error.config.method}-${error.config.url}`; + cancelTokenSources.delete(requestKey); + } + if (error.response && error.response.status === 401) { console.error('[API] Неавторизованный запрос (401):', error.config.url); @@ -56,9 +84,31 @@ apiClient.interceptors.response.use( } ); +// Функция для отмены всех активных запросов +const cancelActiveRequests = () => { + console.log('[API] Отмена всех активных запросов. Количество: ' + cancelTokenSources.size); + cancelTokenSources.forEach((source, key) => { + source.cancel('Запрос отменен из-за блокировки аккаунта'); + console.log(`[API] Запрос ${key} отменен`); + }); + cancelTokenSources.clear(); +}; + +// Функция для явной установки токена аутентификации +const setAuthToken = (token) => { + if (token) { + apiClient.defaults.headers.common['Authorization'] = `Bearer ${token}`; + } else { + delete apiClient.defaults.headers.common['Authorization']; + } +}; // Экспортируем функции для конкретных эндпоинтов export default { + // Добавляем новые утилитарные методы + cancelActiveRequests, + setAuthToken, + register(userData) { return apiClient.post('/auth/register', userData); }, diff --git a/src/services/socketService.js b/src/services/socketService.js index c231846..f3a29e1 100644 --- a/src/services/socketService.js +++ b/src/services/socketService.js @@ -49,25 +49,28 @@ export const connectSocket = () => { // Добавляем обработчик для события блокировки аккаунта socket.on('account_blocked', (data) => { console.log('[SocketService] Получено уведомление о блокировке аккаунта:', data); - // Вызываем функцию обработки блокировки из auth.js тихо, без показа браузерного уведомления - // Отложенный вызов, чтобы избежать показа стандартного уведомления браузера - setTimeout(() => { - handleAccountBlocked(data); - }, 10); + + // Немедленно отключаем сокет + socket.disconnect(); + console.log('[SocketService] Сокет принудительно отключен из-за блокировки аккаунта'); + + // Сразу вызываем функцию обработки блокировки из auth.js, без таймаута + handleAccountBlocked(data); + + // Разрываем все существующие соединения и очищаем состояние сокета + socket = null; }); // Добавляем обработчик для события разблокировки аккаунта socket.on('account_unblocked', (data) => { console.log('[SocketService] Получено уведомление о разблокировке аккаунта:', data); - // Аналогично блокировке, используем setTimeout для предотвращения браузерного уведомления - setTimeout(() => { - // Если есть функция handleAccountUnblocked, вызываем её - if (typeof handleAccountUnblocked === 'function') { - handleAccountUnblocked(data); - } else { - console.log('[SocketService] Аккаунт разблокирован, но обработчик не определен'); - } - }, 10); + + // Сразу вызываем обработчик разблокировки, без таймаута + if (typeof handleAccountUnblocked === 'function') { + handleAccountUnblocked(data); + } else { + console.log('[SocketService] Аккаунт разблокирован, но обработчик не определен'); + } }); // Можно здесь же слушать глобальные события, если нужно