ваше сообщение коммита
This commit is contained in:
@@ -14,7 +14,9 @@ import { ref, computed, watch, onMounted, onUnmounted } from 'vue';
|
||||
import api from '../api/axios';
|
||||
import { getFromStorage, setToStorage, removeFromStorage } from '../utils/storage';
|
||||
import { generateUniqueId } from '../utils/helpers';
|
||||
import websocketService from '../services/websocketService';
|
||||
import websocketModule from '../services/websocketService';
|
||||
|
||||
const { websocketService } = websocketModule;
|
||||
|
||||
function initGuestId() {
|
||||
let id = getFromStorage('guestId', '');
|
||||
@@ -44,6 +46,15 @@ export function useChat(auth) {
|
||||
|
||||
const guestId = ref(initGuestId());
|
||||
|
||||
// Сохраняем ссылки на callback функции WebSocket для правильной отписки
|
||||
const wsCallbacks = {
|
||||
chatMessage: null,
|
||||
conversationUpdated: null,
|
||||
connected: null,
|
||||
disconnected: null,
|
||||
error: null
|
||||
};
|
||||
|
||||
const shouldLoadHistory = computed(() => {
|
||||
return auth.isAuthenticated.value || !!guestId.value;
|
||||
});
|
||||
@@ -423,44 +434,69 @@ export function useChat(auth) {
|
||||
console.log('[useChat] Подключение к WebSocket для пользователя:', auth.user.value.id);
|
||||
websocketService.connect(auth.user.value.id);
|
||||
|
||||
// Подписываемся на события
|
||||
websocketService.on('chat-message', (message) => {
|
||||
// Создаем и сохраняем callback функции
|
||||
wsCallbacks.chatMessage = (message) => {
|
||||
console.log('[useChat] Получено новое сообщение через WebSocket:', message);
|
||||
// Проверяем, что сообщение не дублируется
|
||||
const existingMessage = messages.value.find(m => m.id === message.id);
|
||||
if (!existingMessage) {
|
||||
messages.value.push(message);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
websocketService.on('conversation-updated', (conversationId) => {
|
||||
wsCallbacks.conversationUpdated = (conversationId) => {
|
||||
console.log('[useChat] Обновление диалога через WebSocket:', conversationId);
|
||||
// Можно добавить логику обновления списка диалогов
|
||||
});
|
||||
};
|
||||
|
||||
websocketService.on('connected', () => {
|
||||
wsCallbacks.connected = () => {
|
||||
console.log('[useChat] WebSocket подключен');
|
||||
});
|
||||
};
|
||||
|
||||
websocketService.on('disconnected', () => {
|
||||
wsCallbacks.disconnected = () => {
|
||||
console.log('[useChat] WebSocket отключен');
|
||||
});
|
||||
};
|
||||
|
||||
websocketService.on('error', (error) => {
|
||||
wsCallbacks.error = (error) => {
|
||||
console.error('[useChat] WebSocket ошибка:', error);
|
||||
});
|
||||
};
|
||||
|
||||
// Подписываемся на события
|
||||
websocketService.on('chat-message', wsCallbacks.chatMessage);
|
||||
websocketService.on('conversation-updated', wsCallbacks.conversationUpdated);
|
||||
websocketService.on('connected', wsCallbacks.connected);
|
||||
websocketService.on('disconnected', wsCallbacks.disconnected);
|
||||
websocketService.on('error', wsCallbacks.error);
|
||||
} else {
|
||||
console.log('[useChat] WebSocket не подключен: пользователь не аутентифицирован или данные не загружены');
|
||||
}
|
||||
}
|
||||
|
||||
function cleanupWebSocket() {
|
||||
websocketService.off('chat-message');
|
||||
websocketService.off('conversation-updated');
|
||||
websocketService.off('connected');
|
||||
websocketService.off('disconnected');
|
||||
websocketService.off('error');
|
||||
websocketService.disconnect();
|
||||
// Отписываемся от всех событий, передавая те же callback функции
|
||||
if (websocketService) {
|
||||
if (wsCallbacks.chatMessage) {
|
||||
websocketService.off('chat-message', wsCallbacks.chatMessage);
|
||||
}
|
||||
if (wsCallbacks.conversationUpdated) {
|
||||
websocketService.off('conversation-updated', wsCallbacks.conversationUpdated);
|
||||
}
|
||||
if (wsCallbacks.connected) {
|
||||
websocketService.off('connected', wsCallbacks.connected);
|
||||
}
|
||||
if (wsCallbacks.disconnected) {
|
||||
websocketService.off('disconnected', wsCallbacks.disconnected);
|
||||
}
|
||||
if (wsCallbacks.error) {
|
||||
websocketService.off('error', wsCallbacks.error);
|
||||
}
|
||||
websocketService.disconnect();
|
||||
|
||||
// Очищаем ссылки на callback функции
|
||||
Object.keys(wsCallbacks).forEach(key => {
|
||||
wsCallbacks[key] = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// --- Инициализация ---
|
||||
|
||||
141
frontend/src/composables/useTablesWebSocket.js
Normal file
141
frontend/src/composables/useTablesWebSocket.js
Normal file
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* Copyright (c) 2024-2025 Тарабанов Александр Викторович
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is proprietary and confidential.
|
||||
* Unauthorized copying, modification, or distribution is prohibited.
|
||||
*
|
||||
* For licensing inquiries: info@hb3-accelerator.com
|
||||
* Website: https://hb3-accelerator.com
|
||||
* GitHub: https://github.com/HB3-ACCELERATOR
|
||||
*/
|
||||
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
|
||||
export function useTablesWebSocket() {
|
||||
const ws = ref(null);
|
||||
const isConnected = ref(false);
|
||||
const tableUpdateCallbacks = ref(new Map()); // tableId -> callback
|
||||
const tableRelationsUpdateCallbacks = ref(new Map()); // `${tableId}-${rowId}` -> callback
|
||||
|
||||
function connect() {
|
||||
if (ws.value && ws.value.readyState === WebSocket.OPEN) {
|
||||
return; // Уже подключены
|
||||
}
|
||||
|
||||
const wsProtocol = window.location.protocol === 'https:' ? 'wss' : 'ws';
|
||||
ws.value = new WebSocket(`${wsProtocol}://${window.location.host}/ws`);
|
||||
|
||||
ws.value.onopen = () => {
|
||||
console.log('[TablesWebSocket] Соединение установлено');
|
||||
isConnected.value = true;
|
||||
};
|
||||
|
||||
ws.value.onmessage = (event) => {
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
console.log('[TablesWebSocket] Получено сообщение:', data);
|
||||
|
||||
if (data.type === 'table-updated') {
|
||||
const callbacks = tableUpdateCallbacks.value.get(data.tableId);
|
||||
if (callbacks) {
|
||||
callbacks.forEach(callback => callback(data));
|
||||
}
|
||||
}
|
||||
|
||||
if (data.type === 'table-relations-updated') {
|
||||
const key = `${data.tableId}-${data.rowId}`;
|
||||
const callbacks = tableRelationsUpdateCallbacks.value.get(key);
|
||||
if (callbacks) {
|
||||
callbacks.forEach(callback => callback(data));
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[TablesWebSocket] Ошибка обработки сообщения:', error);
|
||||
}
|
||||
};
|
||||
|
||||
ws.value.onclose = () => {
|
||||
console.log('[TablesWebSocket] Соединение закрыто');
|
||||
isConnected.value = false;
|
||||
// Переподключение через 3 секунды
|
||||
setTimeout(() => {
|
||||
if (!isConnected.value) {
|
||||
connect();
|
||||
}
|
||||
}, 3000);
|
||||
};
|
||||
|
||||
ws.value.onerror = (error) => {
|
||||
console.error('[TablesWebSocket] Ошибка соединения:', error);
|
||||
isConnected.value = false;
|
||||
};
|
||||
}
|
||||
|
||||
function subscribeToTableUpdates(tableId, callback) {
|
||||
if (!tableUpdateCallbacks.value.has(tableId)) {
|
||||
tableUpdateCallbacks.value.set(tableId, []);
|
||||
}
|
||||
tableUpdateCallbacks.value.get(tableId).push(callback);
|
||||
|
||||
// Возвращаем функцию для отписки
|
||||
return () => {
|
||||
const callbacks = tableUpdateCallbacks.value.get(tableId);
|
||||
if (callbacks) {
|
||||
const index = callbacks.indexOf(callback);
|
||||
if (index > -1) {
|
||||
callbacks.splice(index, 1);
|
||||
}
|
||||
if (callbacks.length === 0) {
|
||||
tableUpdateCallbacks.value.delete(tableId);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function subscribeToTableRelationsUpdates(tableId, rowId, callback) {
|
||||
const key = `${tableId}-${rowId}`;
|
||||
if (!tableRelationsUpdateCallbacks.value.has(key)) {
|
||||
tableRelationsUpdateCallbacks.value.set(key, []);
|
||||
}
|
||||
tableRelationsUpdateCallbacks.value.get(key).push(callback);
|
||||
|
||||
// Возвращаем функцию для отписки
|
||||
return () => {
|
||||
const callbacks = tableRelationsUpdateCallbacks.value.get(key);
|
||||
if (callbacks) {
|
||||
const index = callbacks.indexOf(callback);
|
||||
if (index > -1) {
|
||||
callbacks.splice(index, 1);
|
||||
}
|
||||
if (callbacks.length === 0) {
|
||||
tableRelationsUpdateCallbacks.value.delete(key);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function disconnect() {
|
||||
if (ws.value) {
|
||||
ws.value.close();
|
||||
ws.value = null;
|
||||
}
|
||||
isConnected.value = false;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
connect();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
disconnect();
|
||||
});
|
||||
|
||||
return {
|
||||
isConnected,
|
||||
connect,
|
||||
disconnect,
|
||||
subscribeToTableUpdates,
|
||||
subscribeToTableRelationsUpdates
|
||||
};
|
||||
}
|
||||
70
frontend/src/composables/useTagsWebSocket.js
Normal file
70
frontend/src/composables/useTagsWebSocket.js
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Copyright (c) 2024-2025 Тарабанов Александр Викторович
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is proprietary and confidential.
|
||||
* Unauthorized copying, modification, or distribution is prohibited.
|
||||
*
|
||||
* For licensing inquiries: info@hb3-accelerator.com
|
||||
* Website: https://hb3-accelerator.com
|
||||
* GitHub: https://github.com/HB3-ACCELERATOR
|
||||
*/
|
||||
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
import websocketServiceModule from '../services/websocketService';
|
||||
|
||||
const { websocketService } = websocketServiceModule;
|
||||
|
||||
export function useTagsWebSocket() {
|
||||
const tagsUpdateCallbacks = ref([]);
|
||||
let debounceTimer = null;
|
||||
const DEBOUNCE_DELAY = 1000; // 1 секунда
|
||||
|
||||
function onTagsUpdate(callback) {
|
||||
tagsUpdateCallbacks.value.push(callback);
|
||||
|
||||
// Возвращаем функцию для отписки
|
||||
return () => {
|
||||
const index = tagsUpdateCallbacks.value.indexOf(callback);
|
||||
if (index > -1) {
|
||||
tagsUpdateCallbacks.value.splice(index, 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function handleTagsUpdate(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);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
websocketService.on('tags-updated', handleTagsUpdate);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (debounceTimer) {
|
||||
clearTimeout(debounceTimer);
|
||||
}
|
||||
websocketService.off('tags-updated', handleTagsUpdate);
|
||||
});
|
||||
|
||||
return {
|
||||
onTagsUpdate
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user