This commit is contained in:
Professional 2025-05-26 16:49:20 +07:00
parent 71b48b5d25
commit f7d0d71858
3 changed files with 77 additions and 16 deletions

View File

@ -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({

View File

@ -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);
},

View File

@ -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] Аккаунт разблокирован, но обработчик не определен');
}
});
// Можно здесь же слушать глобальные события, если нужно