ваше сообщение коммита
This commit is contained in:
@@ -15,20 +15,61 @@ import { ref, onMounted, onUnmounted } from 'vue';
|
||||
export function useTablesWebSocket() {
|
||||
const ws = ref(null);
|
||||
const isConnected = ref(false);
|
||||
const isConnecting = ref(false); // Добавляем флаг для предотвращения множественных подключений
|
||||
const tableUpdateCallbacks = ref(new Map()); // tableId -> callback
|
||||
const tableRelationsUpdateCallbacks = ref(new Map()); // `${tableId}-${rowId}` -> callback
|
||||
const pingInterval = ref(null); // Интервал для ping сообщений
|
||||
|
||||
function connect() {
|
||||
if (ws.value && ws.value.readyState === WebSocket.OPEN) {
|
||||
console.log('[TablesWebSocket] Уже подключены, пропускаем');
|
||||
return; // Уже подключены
|
||||
}
|
||||
|
||||
const wsProtocol = window.location.protocol === 'https:' ? 'wss' : 'ws';
|
||||
ws.value = new WebSocket(`${wsProtocol}://${window.location.host}/ws`);
|
||||
if (isConnecting.value) {
|
||||
console.log('[TablesWebSocket] Уже пытаемся подключиться, пропускаем');
|
||||
return; // Уже пытаемся подключиться
|
||||
}
|
||||
|
||||
isConnecting.value = true;
|
||||
|
||||
// Определяем правильный URL для WebSocket
|
||||
let wsUrl;
|
||||
if (import.meta.env.DEV) {
|
||||
// В режиме разработки используем прокси через Vite
|
||||
wsUrl = `${window.location.protocol === 'https:' ? 'wss' : 'ws'}://${window.location.host}/ws`;
|
||||
} else {
|
||||
// В продакшене используем тот же хост
|
||||
wsUrl = `${window.location.protocol === 'https:' ? 'wss' : 'ws'}://${window.location.host}/ws`;
|
||||
}
|
||||
|
||||
console.log('[TablesWebSocket] Подключение к:', wsUrl);
|
||||
console.log('[TablesWebSocket] Текущий хост:', window.location.host);
|
||||
console.log('[TablesWebSocket] Протокол:', window.location.protocol);
|
||||
|
||||
try {
|
||||
ws.value = new WebSocket(wsUrl);
|
||||
} catch (error) {
|
||||
console.error('[TablesWebSocket] Ошибка создания WebSocket:', error);
|
||||
isConnecting.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
ws.value.onopen = () => {
|
||||
console.log('[TablesWebSocket] Соединение установлено');
|
||||
isConnected.value = true;
|
||||
isConnecting.value = false;
|
||||
|
||||
// Запускаем ping каждые 30 секунд
|
||||
pingInterval.value = setInterval(() => {
|
||||
if (ws.value && ws.value.readyState === WebSocket.OPEN) {
|
||||
try {
|
||||
ws.value.send(JSON.stringify({ type: 'ping', timestamp: Date.now() }));
|
||||
} catch (error) {
|
||||
console.error('[TablesWebSocket] Ошибка отправки ping:', error);
|
||||
}
|
||||
}
|
||||
}, 30000);
|
||||
};
|
||||
|
||||
ws.value.onmessage = (event) => {
|
||||
@@ -36,6 +77,12 @@ export function useTablesWebSocket() {
|
||||
const data = JSON.parse(event.data);
|
||||
console.log('[TablesWebSocket] Получено сообщение:', data);
|
||||
|
||||
// Обрабатываем pong ответ
|
||||
if (data.type === 'pong') {
|
||||
console.log('[TablesWebSocket] Получен pong ответ');
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.type === 'table-updated') {
|
||||
const callbacks = tableUpdateCallbacks.value.get(data.tableId);
|
||||
if (callbacks) {
|
||||
@@ -55,20 +102,37 @@ export function useTablesWebSocket() {
|
||||
}
|
||||
};
|
||||
|
||||
ws.value.onclose = () => {
|
||||
console.log('[TablesWebSocket] Соединение закрыто');
|
||||
ws.value.onclose = (event) => {
|
||||
console.log('[TablesWebSocket] Соединение закрыто', {
|
||||
code: event.code,
|
||||
reason: event.reason,
|
||||
wasClean: event.wasClean
|
||||
});
|
||||
isConnected.value = false;
|
||||
// Переподключение через 3 секунды
|
||||
setTimeout(() => {
|
||||
if (!isConnected.value) {
|
||||
connect();
|
||||
}
|
||||
}, 3000);
|
||||
isConnecting.value = false;
|
||||
|
||||
// Останавливаем ping интервал
|
||||
if (pingInterval.value) {
|
||||
clearInterval(pingInterval.value);
|
||||
pingInterval.value = null;
|
||||
}
|
||||
|
||||
// Переподключение только если это не было намеренное закрытие
|
||||
if (event.code !== 1000) {
|
||||
setTimeout(() => {
|
||||
if (!isConnected.value && !isConnecting.value) {
|
||||
console.log('[TablesWebSocket] Попытка переподключения...');
|
||||
connect();
|
||||
}
|
||||
}, 3000);
|
||||
}
|
||||
};
|
||||
|
||||
ws.value.onerror = (error) => {
|
||||
console.error('[TablesWebSocket] Ошибка соединения:', error);
|
||||
console.error('[TablesWebSocket] WebSocket readyState:', ws.value?.readyState);
|
||||
isConnected.value = false;
|
||||
isConnecting.value = false;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -117,10 +181,20 @@ export function useTablesWebSocket() {
|
||||
|
||||
function disconnect() {
|
||||
if (ws.value) {
|
||||
ws.value.close();
|
||||
// Останавливаем ping интервал
|
||||
if (pingInterval.value) {
|
||||
clearInterval(pingInterval.value);
|
||||
pingInterval.value = null;
|
||||
}
|
||||
|
||||
// Корректно закрываем соединение
|
||||
if (ws.value.readyState === WebSocket.OPEN) {
|
||||
ws.value.close(1000, 'Manual disconnect');
|
||||
}
|
||||
ws.value = null;
|
||||
}
|
||||
isConnected.value = false;
|
||||
isConnecting.value = false;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@@ -33,24 +33,16 @@ export function useTagsWebSocket() {
|
||||
}
|
||||
|
||||
function handleTagsUpdate(data) {
|
||||
console.log('🏷️ [useTagsWebSocket] Получено обновление тегов:', data);
|
||||
console.log('🏷️ [useTagsWebSocket] Получено уведомление об обновлении тегов:', data);
|
||||
|
||||
// Очищаем предыдущий таймер
|
||||
if (debounceTimer) {
|
||||
clearTimeout(debounceTimer);
|
||||
}
|
||||
|
||||
// Устанавливаем новый таймер для дебаунсинга
|
||||
debounceTimer = setTimeout(() => {
|
||||
console.log('🏷️ [useTagsWebSocket] Выполняем обновление тегов после дебаунсинга');
|
||||
tagsUpdateCallbacks.value.forEach(callback => {
|
||||
try {
|
||||
callback(data);
|
||||
} catch (error) {
|
||||
console.error('Ошибка в callback обновления тегов:', error);
|
||||
}
|
||||
});
|
||||
}, DEBOUNCE_DELAY);
|
||||
// Вызываем все зарегистрированные колбэки
|
||||
tagsUpdateCallbacks.value.forEach(callback => {
|
||||
try {
|
||||
callback(data);
|
||||
} catch (error) {
|
||||
console.error('🏷️ [useTagsWebSocket] Ошибка в колбэке:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@@ -31,6 +31,12 @@ export default {
|
||||
return res.data;
|
||||
} catch (err) {
|
||||
console.error('Ошибка при удалении контакта:', err.response?.status, err.response?.data, err);
|
||||
|
||||
// Если пользователь уже удален (404), считаем это успехом
|
||||
if (err.response?.status === 404) {
|
||||
return { success: true, deleted: 0, message: 'Пользователь уже удален' };
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* GitHub: https://github.com/HB3-ACCELERATOR
|
||||
*/
|
||||
|
||||
import axios from 'axios';
|
||||
import api from '@/api/axios';
|
||||
|
||||
/**
|
||||
* Сервис для работы с DLE v2 (Digital Legal Entity)
|
||||
@@ -24,7 +24,7 @@ class DLEV2Service {
|
||||
*/
|
||||
async createDLE(dleParams) {
|
||||
try {
|
||||
const response = await axios.post('/api/dle-v2', dleParams);
|
||||
const response = await api.post('/dle-v2', dleParams);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('Ошибка при создании DLE v2:', error);
|
||||
@@ -38,7 +38,7 @@ class DLEV2Service {
|
||||
*/
|
||||
async getAllDLEs() {
|
||||
try {
|
||||
const response = await axios.get('/api/dle-v2');
|
||||
const response = await api.get('/dle-v2');
|
||||
return response.data.data || [];
|
||||
} catch (error) {
|
||||
console.error('Ошибка при получении списка DLE v2:', error);
|
||||
@@ -52,7 +52,7 @@ class DLEV2Service {
|
||||
*/
|
||||
async getDefaults() {
|
||||
try {
|
||||
const response = await axios.get('/api/dle-v2/defaults');
|
||||
const response = await api.get('/dle-v2/defaults');
|
||||
return response.data.data;
|
||||
} catch (error) {
|
||||
console.error('Ошибка при получении настроек по умолчанию DLE v2:', error);
|
||||
@@ -73,7 +73,7 @@ class DLEV2Service {
|
||||
*/
|
||||
async deleteDLE(dleAddress) {
|
||||
try {
|
||||
const response = await axios.delete(`/api/dle-v2/${dleAddress}`);
|
||||
const response = await api.delete(`/dle-v2/${dleAddress}`);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error('Ошибка при удалении DLE v2:', error);
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
* GitHub: https://github.com/HB3-ACCELERATOR
|
||||
*/
|
||||
|
||||
import axios from 'axios';
|
||||
import api from '@/api/axios';
|
||||
|
||||
export default {
|
||||
async getMessagesByUserId(userId) {
|
||||
if (!userId) return [];
|
||||
const { data } = await axios.get(`/messages?userId=${userId}`);
|
||||
const { data } = await api.get(`/messages?userId=${userId}`);
|
||||
return data;
|
||||
},
|
||||
async sendMessage({ conversationId, message, attachments = [], toUserId }) {
|
||||
@@ -26,7 +26,7 @@ export default {
|
||||
attachments.forEach(file => {
|
||||
formData.append('attachments', file);
|
||||
});
|
||||
const { data } = await axios.post('/chat/message', formData, {
|
||||
const { data } = await api.post('/chat/message', formData, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
withCredentials: true
|
||||
});
|
||||
@@ -34,20 +34,20 @@ export default {
|
||||
},
|
||||
async getMessagesByConversationId(conversationId) {
|
||||
if (!conversationId) return [];
|
||||
const { data } = await axios.get(`/messages?conversationId=${conversationId}`);
|
||||
const { data } = await api.get(`/messages?conversationId=${conversationId}`);
|
||||
return data;
|
||||
},
|
||||
async getConversationByUserId(userId) {
|
||||
if (!userId) return null;
|
||||
const { data } = await axios.get(`/messages/conversations?userId=${userId}`);
|
||||
const { data } = await api.get(`/messages/conversations?userId=${userId}`);
|
||||
return data;
|
||||
},
|
||||
async generateAiDraft(conversationId, messages, language = 'auto') {
|
||||
const { data } = await axios.post('/chat/ai-draft', { conversationId, messages, language });
|
||||
const { data } = await api.post('/chat/ai-draft', { conversationId, messages, language });
|
||||
return data;
|
||||
},
|
||||
async broadcastMessage({ userId, message }) {
|
||||
const { data } = await axios.post('/messages/broadcast', {
|
||||
const { data } = await api.post('/messages/broadcast', {
|
||||
user_id: userId,
|
||||
content: message
|
||||
}, {
|
||||
@@ -56,7 +56,7 @@ export default {
|
||||
return data;
|
||||
},
|
||||
async deleteMessagesHistory(userId) {
|
||||
const { data } = await axios.delete(`/messages/history/${userId}`, {
|
||||
const { data } = await api.delete(`/messages/history/${userId}`, {
|
||||
withCredentials: true
|
||||
});
|
||||
return data;
|
||||
@@ -64,6 +64,6 @@ export default {
|
||||
};
|
||||
|
||||
export async function getAllMessages() {
|
||||
const { data } = await axios.get('/messages');
|
||||
const { data } = await api.get('/messages');
|
||||
return data;
|
||||
}
|
||||
@@ -139,7 +139,7 @@ class WebSocketService {
|
||||
break;
|
||||
|
||||
case 'tags-updated':
|
||||
console.log('🏷️ [WebSocket] Обновление тегов клиентов');
|
||||
console.log('🔔 [websocketService] Получено сообщение tags-updated');
|
||||
this.emit('tags-updated');
|
||||
break;
|
||||
|
||||
|
||||
@@ -54,8 +54,13 @@ async function loadContact() {
|
||||
isLoading.value = true;
|
||||
try {
|
||||
contact.value = await contactsService.getContactById(route.params.id);
|
||||
if (!contact.value) {
|
||||
error.value = 'Контакт не найден';
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Ошибка загрузки контакта:', e);
|
||||
contact.value = null;
|
||||
error.value = 'Контакт не найден';
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
@@ -66,9 +71,17 @@ async function deleteContact() {
|
||||
isDeleting.value = true;
|
||||
error.value = '';
|
||||
try {
|
||||
await contactsService.deleteContact(contact.value.id);
|
||||
router.push({ name: 'crm' });
|
||||
const result = await contactsService.deleteContact(contact.value.id);
|
||||
console.log('Результат удаления:', result);
|
||||
|
||||
// Если удаление успешно или пользователь уже удален
|
||||
if (result.success || result.message === 'Пользователь уже удален') {
|
||||
router.push({ name: 'contacts-list' });
|
||||
} else {
|
||||
error.value = 'Ошибка при удалении контакта';
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Ошибка при удалении:', e);
|
||||
error.value = 'Ошибка при удалении контакта';
|
||||
} finally {
|
||||
isDeleting.value = false;
|
||||
@@ -76,7 +89,7 @@ async function deleteContact() {
|
||||
}
|
||||
|
||||
function cancelDelete() {
|
||||
router.push({ name: 'contact-details', params: { id: route.params.id } });
|
||||
router.push({ name: 'contacts-list' });
|
||||
}
|
||||
|
||||
onMounted(loadContact);
|
||||
|
||||
Reference in New Issue
Block a user