@@ -169,7 +175,9 @@ import axios from 'axios';
import { ElSelect, ElOption, ElButton } from 'element-plus';
import websocketService from '../../services/websocketService';
import cacheService from '../../services/cacheService';
+import { useTagsWebSocket } from '../../composables/useTagsWebSocket';
let unsubscribeFromTableUpdate = null;
+let unsubscribeFromTagsUpdate = null;
const { isAdmin } = useAuthContext();
const rebuilding = ref(false);
@@ -269,6 +277,10 @@ const openedRowMenuId = ref(null);
const colMenuStyle = ref('');
const rowMenuStyle = ref('');
+// Меню добавления
+const showAddMenu = ref(false);
+const addMenuStyle = ref('');
+
function closeAddColModal() {
showAddColModal.value = false;
newColName.value = '';
@@ -546,12 +558,77 @@ onMounted(() => {
cacheService.clearTableCache(props.tableId);
fetchTable();
});
+
+ // Подписка на WebSocket обновления тегов
+ const { onTagsUpdate } = useTagsWebSocket();
+ console.log('[UserTableView] Подписываемся на обновления тегов для таблицы:', props.tableId);
+ console.log('[UserTableView] onTagsUpdate функция:', typeof onTagsUpdate);
+ unsubscribeFromTagsUpdate = onTagsUpdate(async (data) => {
+ console.log('[UserTableView] 🔔 ПОЛУЧЕНО СОБЫТИЕ TAGS-UPDATED!');
+ console.log('[UserTableView] Получено событие tags-updated, обновляем данные для таблицы:', props.tableId, data);
+
+ // Если есть информация о конкретной строке, обновляем только её
+ if (data && data.rowId) {
+ console.log('[UserTableView] Точечное обновление для строки:', data.rowId);
+ try {
+ // Очищаем кэш relations только для конкретной строки
+ const tagColumns = columns.value.filter(col =>
+ col.type === 'multirelation' &&
+ col.options?.relatedTableId
+ );
+
+ for (const col of tagColumns) {
+ cacheService.clearRelationsData(data.rowId, col.id);
+ }
+
+ console.log('[UserTableView] Кэш relations очищен для строки, обновляем данные строки:', data.rowId);
+
+ // Обновляем только данные конкретной строки
+ await updateRowData(data.rowId);
+ console.log('[UserTableView] Данные строки обновлены:', data.rowId);
+ } catch (error) {
+ console.error('[UserTableView] Ошибка при точечном обновлении:', error);
+ // Fallback: полная перезагрузка при ошибке
+ await fetchTable();
+ }
+ } else {
+ // Если нет информации о строке, используем старую логику
+ console.log('[UserTableView] Общее обновление тегов');
+ try {
+ // Очищаем кэш relations для всех строк этой таблицы
+ const tableRows = rows.value || [];
+ for (const row of tableRows) {
+ // Находим колонки с мульти-связями (теги)
+ const tagColumns = columns.value.filter(col =>
+ col.type === 'multirelation' &&
+ col.options?.relatedTableId
+ );
+
+ for (const col of tagColumns) {
+ cacheService.clearRelationsData(row.id, col.id);
+ }
+ }
+
+ console.log('[UserTableView] Кэш relations очищен, перезагружаем данные таблицы:', props.tableId);
+ await fetchTable();
+ console.log('[UserTableView] Данные таблицы перезагружены:', props.tableId);
+ } catch (error) {
+ console.error('[UserTableView] Ошибка при обновлении после tags-updated:', error);
+ // Fallback: полная перезагрузка при ошибке
+ cacheService.clearTableCache(props.tableId);
+ await fetchTable();
+ }
+ }
+ });
});
onUnmounted(() => {
if (unsubscribeFromTableUpdate) {
unsubscribeFromTableUpdate();
}
+ if (unsubscribeFromTagsUpdate) {
+ unsubscribeFromTagsUpdate();
+ }
});
// Для редактирования ячеек
@@ -619,6 +696,14 @@ function openRowMenu(row, event) {
function closeMenus() {
openedColMenuId.value = null;
openedRowMenuId.value = null;
+ showAddMenu.value = false;
+}
+
+function openAddMenu(event) {
+ showAddMenu.value = true;
+ openedColMenuId.value = null;
+ openedRowMenuId.value = null;
+ setMenuPosition(event, addMenuStyle);
}
function setMenuPosition(event, styleRef) {
// Позиционируем меню под кнопкой
@@ -676,6 +761,54 @@ async function rebuildIndex() {
}
}
+// Функция для точечного обновления данных конкретной строки
+async function updateRowData(rowId) {
+ const startTime = Date.now();
+ console.log(`[UserTableView] 🔄 Начало обновления данных строки ${rowId}`);
+
+ try {
+ // Находим строку в текущих данных
+ const rowIndex = rows.value.findIndex(row => row.id === rowId);
+ if (rowIndex === -1) {
+ console.log(`[UserTableView] Строка ${rowId} не найдена в текущих данных`);
+ return;
+ }
+
+ // Загружаем relations только для этой строки
+ const tagColumns = columns.value.filter(col =>
+ col.type === 'multirelation' &&
+ col.options?.relatedTableId
+ );
+
+ if (tagColumns.length > 0) {
+ console.log(`[UserTableView] 🔄 Загружаем relations для строки ${rowId} (${tagColumns.length} столбцов)`);
+
+ const relationPromises = tagColumns.map(col =>
+ fetch(`/api/tables/${col.table_id}/row/${rowId}/relations`)
+ .then(res => res.json())
+ .then(relations => {
+ // Сохраняем в кэш
+ cacheService.setRelationsData(rowId, col.id, relations);
+ return { rowId, colId: col.id, relations };
+ })
+ .catch(error => {
+ console.error(`[UserTableView] Ошибка загрузки relations для row:${rowId} col:${col.id}:`, error);
+ return { rowId, colId: col.id, relations: [] };
+ })
+ );
+
+ await Promise.all(relationPromises);
+ console.log(`[UserTableView] ✅ Relations для строки ${rowId} обновлены`);
+ }
+
+ const endTime = Date.now();
+ console.log(`[UserTableView] ✅ Завершено обновление строки ${rowId} за ${endTime - startTime}ms`);
+ } catch (error) {
+ console.error(`[UserTableView] ❌ Ошибка при обновлении строки ${rowId}:`, error);
+ throw error;
+ }
+}
+