ваше сообщение коммита

This commit is contained in:
2025-07-27 20:55:24 +03:00
parent 6dbaf91121
commit 34be65743b
14 changed files with 1124 additions and 126 deletions

View File

@@ -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;
});
}
}
// --- Инициализация ---

View 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
};
}

View 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
};
}