Files
minicrm/public/doc.js
2026-02-07 14:41:57 +05:00

1001 lines
45 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Глобальные переменные
let currentUser = null;
let isAdmin = false;
let currentTab = 'groups';
let groups = [];
let idusers = [];
let allUsers = [];
let currentPage = {
groups: 1,
idusers: 1
};
const itemsPerPage = 20;
let deleteCallback = null;
let deleteParams = null;
// Инициализация при загрузке страницы
document.addEventListener('DOMContentLoaded', function() {
checkAuth();
setupEventListeners();
});
// Проверка аутентификации
async function checkAuth() {
try {
const response = await fetch('/api/user');
if (!response.ok) {
window.location.href = '/';
return;
}
const data = await response.json();
if (data.user) {
currentUser = data.user;
isAdmin = currentUser.role === 'admin';
document.getElementById('userName').textContent = currentUser.name;
document.getElementById('userRole').textContent = `Роль: ${currentUser.role}`;
// Загружаем начальные данные
loadGroups();
loadAllUsers();
loadIdUsers();
loadStats();
} else {
window.location.href = '/';
}
} catch (error) {
console.error('Ошибка проверки аутентификации:', error);
window.location.href = '/';
}
}
// Настройка обработчиков событий
function setupEventListeners() {
// Переключение вкладок
document.querySelectorAll('.tab').forEach(tab => {
tab.addEventListener('click', function() {
const tabId = this.getAttribute('data-tab');
switchTab(tabId);
});
});
// Поиск в таблице групп
document.getElementById('groupSearch').addEventListener('input', debounce(function() {
filterGroups();
}, 300));
// Фильтры групп
document.getElementById('groupServiceTypeFilter').addEventListener('change', filterGroups);
document.getElementById('groupStatusFilter').addEventListener('change', filterGroups);
// Поиск в таблице идентификаторов
document.getElementById('iduserSearch').addEventListener('input', debounce(function() {
filterIdUsers();
}, 300));
// Фильтры идентификаторов
document.getElementById('iduserServiceTypeFilter').addEventListener('change', filterIdUsers);
document.getElementById('iduserGroupFilter').addEventListener('change', filterIdUsers);
document.getElementById('iduserStatusFilter').addEventListener('change', filterIdUsers);
}
// Дебаунс для поиска
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
// Переключение вкладок
function switchTab(tabId) {
currentTab = tabId;
// Обновляем активные вкладки
document.querySelectorAll('.tab').forEach(tab => {
tab.classList.remove('active');
if (tab.getAttribute('data-tab') === tabId) {
tab.classList.add('active');
}
});
// Показываем активный контент
document.querySelectorAll('.tab-content').forEach(content => {
content.classList.remove('active');
if (content.id === `tab-${tabId}`) {
content.classList.add('active');
}
});
}
// Загрузка всех пользователей
async function loadAllUsers() {
try {
const response = await fetch('/api/users');
if (!response.ok) throw new Error('Ошибка загрузки пользователей');
allUsers = await response.json();
// Заполняем select в форме
const select = document.getElementById('iduserUserId');
select.innerHTML = '<option value="">Выберите пользователя</option>';
allUsers.forEach(user => {
const option = document.createElement('option');
option.value = user.id;
option.textContent = `${user.name} (${user.login})`;
select.appendChild(option);
});
} catch (error) {
console.error('Ошибка загрузки пользователей:', error);
}
}
// Загрузка групп
async function loadGroups() {
try {
const tableBody = document.getElementById('groupsTableBody');
tableBody.innerHTML = '<tr><td colspan="8" class="loading"><i class="fas fa-spinner fa-spin"></i> Загрузка групп...</td></tr>';
const response = await fetch('/api2/groups');
if (!response.ok) throw new Error('Ошибка загрузки групп');
groups = await response.json();
// Заполняем фильтр групп для идентификаторов
const groupFilter = document.getElementById('iduserGroupFilter');
const currentValue = groupFilter.value;
groupFilter.innerHTML = '<option value="">Все группы</option>';
groups.forEach(group => {
const option = document.createElement('option');
option.value = group.id;
option.textContent = group.name;
groupFilter.appendChild(option);
});
if (currentValue) {
groupFilter.value = currentValue;
}
renderGroups();
} catch (error) {
console.error('Ошибка загрузки групп:', error);
document.getElementById('groupsTableBody').innerHTML =
'<tr><td colspan="8" class="error">Ошибка загрузки групп: ' + error.message + '</td></tr>';
}
}
// Отображение групп
function renderGroups(filteredGroups = null) {
const groupsToRender = filteredGroups || groups;
const tableBody = document.getElementById('groupsTableBody');
if (groupsToRender.length === 0) {
tableBody.innerHTML = '<tr><td colspan="8" class="no-data">Нет данных для отображения</td></tr>';
document.getElementById('groupsPagination').innerHTML = '';
return;
}
// Пагинация
const totalPages = Math.ceil(groupsToRender.length / itemsPerPage);
const startIndex = (currentPage.groups - 1) * itemsPerPage;
const endIndex = startIndex + itemsPerPage;
const pageGroups = groupsToRender.slice(startIndex, endIndex);
// Очищаем таблицу
tableBody.innerHTML = '';
// Заполняем таблицу
pageGroups.forEach(group => {
const row = document.createElement('tr');
// Бейдж для типа сервиса
let serviceTypeBadge = '';
switch(group.service_type) {
case 'sberbank':
serviceTypeBadge = '<span class="badge badge-sberbank">Сбербанк</span>';
break;
case 'yandex':
serviceTypeBadge = '<span class="badge badge-yandex">Яндекс</span>';
break;
case 'ldap':
serviceTypeBadge = '<span class="badge badge-ldap">LDAP</span>';
break;
default:
serviceTypeBadge = '<span class="badge badge-other">Прочие</span>';
}
row.innerHTML = `
<td>${group.id}</td>
<td><strong>${group.name}</strong></td>
<td>${serviceTypeBadge}</td>
<td>${group.description || '-'}</td>
<td>${group.is_active ? '<span class="status-active">Активна</span>' : '<span class="status-inactive">Неактивна</span>'}</td>
<td>${formatDate(group.created_at)}</td>
<td>${formatDate(group.updated_at)}</td>
<td class="actions">
${isAdmin ? `
<button class="btn btn-primary btn-small" onclick="editGroup(${group.id})">
<i class="fas fa-edit"></i>
</button>
<button class="btn btn-danger btn-small" onclick="confirmDeleteGroup(${group.id})">
<i class="fas fa-trash"></i>
</button>
` : ''}
</td>
`;
tableBody.appendChild(row);
});
// Пагинация
renderPagination('groups', totalPages);
}
// Фильтрация групп
function filterGroups() {
const searchText = document.getElementById('groupSearch').value.toLowerCase();
const serviceType = document.getElementById('groupServiceTypeFilter').value;
const statusFilter = document.getElementById('groupStatusFilter').value;
const filtered = groups.filter(group => {
// Поиск по тексту
const matchesSearch = !searchText ||
group.name.toLowerCase().includes(searchText) ||
(group.description && group.description.toLowerCase().includes(searchText));
// Фильтр по типу сервиса
const matchesServiceType = !serviceType || group.service_type === serviceType;
// Фильтр по статусу
const matchesStatus = !statusFilter ||
(statusFilter === 'true' ? group.is_active : !group.is_active);
return matchesSearch && matchesServiceType && matchesStatus;
});
currentPage.groups = 1;
renderGroups(filtered);
}
// Загрузка идентификаторов пользователей
async function loadIdUsers() {
try {
const tableBody = document.getElementById('idusersTableBody');
tableBody.innerHTML = '<tr><td colspan="11" class="loading"><i class="fas fa-spinner fa-spin"></i> Загрузка идентификаторов...</td></tr>';
const response = await fetch('/api2/idusers');
if (!response.ok) throw new Error('Ошибка загрузки идентификаторов');
idusers = await response.json();
renderIdUsers();
} catch (error) {
console.error('Ошибка загрузки идентификаторов:', error);
document.getElementById('idusersTableBody').innerHTML =
'<tr><td colspan="11" class="error">Ошибка загрузки идентификаторов: ' + error.message + '</td></tr>';
}
}
// Отображение идентификаторов пользователей
function renderIdUsers(filteredIdUsers = null) {
const idusersToRender = filteredIdUsers || idusers;
const tableBody = document.getElementById('idusersTableBody');
if (idusersToRender.length === 0) {
tableBody.innerHTML = '<tr><td colspan="11" class="no-data">Нет данных для отображения</td></tr>';
document.getElementById('idusersPagination').innerHTML = '';
return;
}
// Пагинация
const totalPages = Math.ceil(idusersToRender.length / itemsPerPage);
const startIndex = (currentPage.idusers - 1) * itemsPerPage;
const endIndex = startIndex + itemsPerPage;
const pageIdUsers = idusersToRender.slice(startIndex, endIndex);
// Очищаем таблицу
tableBody.innerHTML = '';
// Заполняем таблицу
pageIdUsers.forEach(iduser => {
const row = document.createElement('tr');
// Бейдж для типа сервиса
let serviceTypeBadge = '';
switch(iduser.service_type) {
case 'sberbank':
serviceTypeBadge = '<span class="badge badge-sberbank">Сбербанк</span>';
break;
case 'yandex':
serviceTypeBadge = '<span class="badge badge-yandex">Яндекс</span>';
break;
case 'ldap':
serviceTypeBadge = '<span class="badge badge-ldap">LDAP</span>';
break;
default:
serviceTypeBadge = '<span class="badge badge-other">Прочие</span>';
}
// Превью метаданных
let metadataPreview = '-';
if (iduser.metadata && Object.keys(iduser.metadata).length > 0) {
metadataPreview = `<div class="metadata-preview" title="Нажмите для просмотра" onclick="showMetadata('${escapeHtml(JSON.stringify(iduser.metadata, null, 2))}')">
${Object.keys(iduser.metadata).length} поле(й)
</div>`;
}
row.innerHTML = `
<td>${iduser.id}</td>
<td>
<strong>${iduser.user_name || 'Неизвестно'}</strong><br>
<small>${iduser.user_login || '-'}</small>
</td>
<td>${serviceTypeBadge}</td>
<td><strong>${iduser.external_id}</strong></td>
<td>${iduser.login || '-'}</td>
<td>${iduser.ldap_group || '-'}</td>
<td>${iduser.group_name || '-'}</td>
<td>${metadataPreview}</td>
<td>${iduser.is_active ? '<span class="status-active">Активен</span>' : '<span class="status-inactive">Неактивен</span>'}</td>
<td>${formatDate(iduser.created_at)}</td>
<td class="actions">
${isAdmin ? `
<button class="btn btn-primary btn-small" onclick="editIdUser(${iduser.id})">
<i class="fas fa-edit"></i>
</button>
<button class="btn btn-danger btn-small" onclick="confirmDeleteIdUser(${iduser.id})">
<i class="fas fa-trash"></i>
</button>
` : ''}
</td>
`;
tableBody.appendChild(row);
});
// Пагинация
renderPagination('idusers', totalPages);
}
// Фильтрация идентификаторов пользователей
function filterIdUsers() {
const searchText = document.getElementById('iduserSearch').value.toLowerCase();
const serviceType = document.getElementById('iduserServiceTypeFilter').value;
const groupId = document.getElementById('iduserGroupFilter').value;
const statusFilter = document.getElementById('iduserStatusFilter').value;
const filtered = idusers.filter(iduser => {
// Поиск по тексту
const matchesSearch = !searchText ||
iduser.external_id.toLowerCase().includes(searchText) ||
(iduser.login && iduser.login.toLowerCase().includes(searchText)) ||
(iduser.user_name && iduser.user_name.toLowerCase().includes(searchText)) ||
(iduser.user_login && iduser.user_login.toLowerCase().includes(searchText));
// Фильтр по типу сервиса
const matchesServiceType = !serviceType || iduser.service_type === serviceType;
// Фильтр по группе
const matchesGroup = !groupId || iduser.group_id == groupId;
// Фильтр по статусу
const matchesStatus = !statusFilter ||
(statusFilter === 'true' ? iduser.is_active : !iduser.is_active);
return matchesSearch && matchesServiceType && matchesGroup && matchesStatus;
});
currentPage.idusers = 1;
renderIdUsers(filtered);
}
// Загрузка статистики
async function loadStats() {
try {
const statsGrid = document.getElementById('statsGrid');
statsGrid.innerHTML = '<div class="loading"><i class="fas fa-spinner fa-spin"></i> Загрузка статистики...</div>';
const response = await fetch('/api2/idusers/stats');
if (!response.ok) throw new Error('Ошибка загрузки статистики');
const stats = await response.json();
renderStats(stats);
} catch (error) {
console.error('Ошибка загрузки статистики:', error);
document.getElementById('statsGrid').innerHTML =
'<div class="error">Ошибка загрузки статистики: ' + error.message + '</div>';
}
}
// Отображение статистики
function renderStats(stats) {
const statsGrid = document.getElementById('statsGrid');
const tableBody = document.getElementById('statsTableBody');
// Статистические карточки
statsGrid.innerHTML = `
<div class="stat-card">
<div class="stat-label">Всего идентификаторов</div>
<div class="stat-value">${stats.totals.total_identifiers || 0}</div>
</div>
<div class="stat-card">
<div class="stat-label">Уникальных пользователей</div>
<div class="stat-value">${stats.totals.total_users || 0}</div>
</div>
<div class="stat-card">
<div class="stat-label">Активных идентификаторов</div>
<div class="stat-value">${stats.totals.total_active || 0}</div>
</div>
<div class="stat-card">
<div class="stat-label">Обновлено</div>
<div class="stat-value">${formatDate(stats.timestamp, 'time')}</div>
</div>
`;
// Таблица по типам сервисов
tableBody.innerHTML = '';
if (stats.by_service_type && stats.by_service_type.length > 0) {
const total = stats.totals.total_identifiers || 1;
stats.by_service_type.forEach(stat => {
const percentage = Math.round((stat.total_count / total) * 100);
const row = document.createElement('tr');
row.innerHTML = `
<td>
<span class="badge badge-${stat.service_type}">
${getServiceTypeName(stat.service_type)}
</span>
</td>
<td>${stat.total_count}</td>
<td>${stat.active_count}</td>
<td>${stat.unique_users}</td>
<td>
<div style="background: #e2e8f0; height: 10px; border-radius: 5px; margin-top: 5px;">
<div style="width: ${percentage}%; background: #667eea; height: 100%; border-radius: 5px;"></div>
</div>
${percentage}%
</td>
`;
tableBody.appendChild(row);
});
} else {
tableBody.innerHTML = '<tr><td colspan="5" class="no-data">Нет данных для отображения</td></tr>';
}
}
// Модальное окно для добавления группы
function showAddGroupModal() {
if (!isAdmin) {
alert('Недостаточно прав');
return;
}
document.getElementById('groupModalTitle').textContent = 'Добавить группу';
document.getElementById('groupId').value = '';
document.getElementById('groupForm').reset();
document.getElementById('groupIsActive').checked = true;
document.getElementById('groupMessage').innerHTML = '';
document.getElementById('groupModal').classList.add('active');
}
// Модальное окно для редактирования группы
async function editGroup(id) {
if (!isAdmin) {
alert('Недостаточно прав');
return;
}
try {
const response = await fetch(`/api2/groups/${id}`);
if (!response.ok) throw new Error('Ошибка загрузки группы');
const group = await response.json();
document.getElementById('groupModalTitle').textContent = 'Редактировать группу';
document.getElementById('groupId').value = group.id;
document.getElementById('groupName').value = group.name;
document.getElementById('groupDescription').value = group.description || '';
document.getElementById('groupServiceType').value = group.service_type;
document.getElementById('groupIsActive').checked = group.is_active;
document.getElementById('groupMessage').innerHTML = '';
document.getElementById('groupModal').classList.add('active');
} catch (error) {
console.error('Ошибка загрузки группы:', error);
alert('Ошибка загрузки группы: ' + error.message);
}
}
// Закрытие модального окна группы
function closeGroupModal() {
document.getElementById('groupModal').classList.remove('active');
}
// Сохранение группы
async function saveGroup(event) {
event.preventDefault();
if (!isAdmin) {
alert('Недостаточно прав');
return;
}
const groupId = document.getElementById('groupId').value;
const isEdit = !!groupId;
const groupData = {
name: document.getElementById('groupName').value,
description: document.getElementById('groupDescription').value,
service_type: document.getElementById('groupServiceType').value,
is_active: document.getElementById('groupIsActive').checked
};
try {
const url = isEdit ? `/api2/groups/${groupId}` : '/api2/groups';
const method = isEdit ? 'PUT' : 'POST';
const response = await fetch(url, {
method: method,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(groupData)
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error || 'Ошибка сохранения');
}
const result = await response.json();
// Показываем сообщение об успехе
document.getElementById('groupMessage').innerHTML = `
<div class="success">
<i class="fas fa-check-circle"></i>
Группа успешно ${isEdit ? 'обновлена' : 'создана'}!
</div>
`;
// Обновляем список групп
setTimeout(() => {
closeGroupModal();
loadGroups();
}, 1500);
} catch (error) {
console.error('Ошибка сохранения группы:', error);
document.getElementById('groupMessage').innerHTML = `
<div class="error">
<i class="fas fa-exclamation-circle"></i>
Ошибка: ${error.message}
</div>
`;
}
}
// Подтверждение удаления группы
function confirmDeleteGroup(id) {
if (!isAdmin) {
alert('Недостаточно прав');
return;
}
const group = groups.find(g => g.id == id);
if (!group) return;
document.getElementById('confirmModalTitle').textContent = 'Удаление группы';
document.getElementById('confirmMessage').textContent = `Вы уверены, что хотите удалить группу "${group.name}"?`;
deleteCallback = deleteGroup;
deleteParams = { id };
document.getElementById('confirmModal').classList.add('active');
}
// Удаление группы
async function deleteGroup(params) {
try {
const response = await fetch(`/api2/groups/${params.id}`, {
method: 'DELETE'
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error || 'Ошибка удаления');
}
const result = await response.json();
if (result.success) {
// Показываем сообщение об успехе
alert('Группа успешно удалена');
// Обновляем список групп
loadGroups();
} else {
throw new Error(result.message || 'Ошибка удаления');
}
} catch (error) {
console.error('Ошибка удаления группы:', error);
alert('Ошибка удаления группы: ' + error.message);
}
}
// Модальное окно для добавления идентификатора
function showAddIdUserModal() {
if (!isAdmin) {
alert('Недостаточно прав');
return;
}
document.getElementById('iduserModalTitle').textContent = 'Добавить идентификатор';
document.getElementById('iduserId').value = '';
document.getElementById('iduserForm').reset();
document.getElementById('iduserIsActive').checked = true;
document.getElementById('iduserMessage').innerHTML = '';
// Обновляем опции групп
updateGroupOptions();
document.getElementById('iduserModal').classList.add('active');
}
// Модальное окно для редактирования идентификатора
async function editIdUser(id) {
if (!isAdmin) {
alert('Недостаточно прав');
return;
}
try {
const response = await fetch(`/api2/idusers/${id}`);
if (!response.ok) throw new Error('Ошибка загрузки идентификатора');
const iduser = await response.json();
document.getElementById('iduserModalTitle').textContent = 'Редактировать идентификатор';
document.getElementById('iduserId').value = iduser.id;
document.getElementById('iduserUserId').value = iduser.user_id;
document.getElementById('iduserExternalId').value = iduser.external_id;
document.getElementById('iduserLogin').value = iduser.login || '';
document.getElementById('iduserLdapGroup').value = iduser.ldap_group || '';
document.getElementById('iduserServiceType').value = iduser.service_type;
document.getElementById('iduserIsActive').checked = iduser.is_active;
// Устанавливаем метаданные
if (iduser.metadata && Object.keys(iduser.metadata).length > 0) {
document.getElementById('iduserMetadata').value = JSON.stringify(iduser.metadata, null, 2);
} else {
document.getElementById('iduserMetadata').value = '';
}
// Обновляем опции групп и выбираем текущую
updateGroupOptions().then(() => {
document.getElementById('iduserGroupId').value = iduser.group_id || '';
});
document.getElementById('iduserMessage').innerHTML = '';
document.getElementById('iduserModal').classList.add('active');
} catch (error) {
console.error('Ошибка загрузки идентификатора:', error);
alert('Ошибка загрузки идентификатора: ' + error.message);
}
}
// Обновление опций групп в зависимости от типа сервиса
async function updateGroupOptions() {
const serviceType = document.getElementById('iduserServiceType').value;
const groupSelect = document.getElementById('iduserGroupId');
// Загружаем группы, если еще не загружены
if (groups.length === 0) {
await loadGroups();
}
// Фильтруем группы по типу сервиса
const filteredGroups = serviceType ?
groups.filter(g => g.service_type === serviceType && g.is_active) :
groups.filter(g => g.is_active);
// Сохраняем текущее значение
const currentValue = groupSelect.value;
// Обновляем опции
groupSelect.innerHTML = '<option value="">Без группы</option>';
filteredGroups.forEach(group => {
const option = document.createElement('option');
option.value = group.id;
option.textContent = group.name;
groupSelect.appendChild(option);
});
// Восстанавливаем значение, если оно есть в новых опциях
if (currentValue && filteredGroups.some(g => g.id == currentValue)) {
groupSelect.value = currentValue;
}
return Promise.resolve();
}
// Закрытие модального окна идентификатора
function closeIdUserModal() {
document.getElementById('iduserModal').classList.remove('active');
}
// Сохранение идентификатора
async function saveIdUser(event) {
event.preventDefault();
if (!isAdmin) {
alert('Недостаточно прав');
return;
}
const iduserId = document.getElementById('iduserId').value;
const isEdit = !!iduserId;
// Парсим метаданные
let metadata = null;
const metadataText = document.getElementById('iduserMetadata').value.trim();
if (metadataText) {
try {
metadata = JSON.parse(metadataText);
} catch (error) {
document.getElementById('iduserMessage').innerHTML = `
<div class="error">
<i class="fas fa-exclamation-circle"></i>
Ошибка в формате JSON: ${error.message}
</div>
`;
return;
}
}
const iduserData = {
user_id: parseInt(document.getElementById('iduserUserId').value),
service_type: document.getElementById('iduserServiceType').value,
external_id: document.getElementById('iduserExternalId').value,
login: document.getElementById('iduserLogin').value || undefined,
ldap_group: document.getElementById('iduserLdapGroup').value || undefined,
group_id: document.getElementById('iduserGroupId').value || undefined,
metadata: metadata,
is_active: document.getElementById('iduserIsActive').checked
};
try {
const url = isEdit ? `/api2/idusers/${iduserId}` : '/api2/idusers';
const method = isEdit ? 'PUT' : 'POST';
const response = await fetch(url, {
method: method,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(iduserData)
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error || 'Ошибка сохранения');
}
const result = await response.json();
// Показываем сообщение об успехе
document.getElementById('iduserMessage').innerHTML = `
<div class="success">
<i class="fas fa-check-circle"></i>
Идентификатор успешно ${isEdit ? 'обновлен' : 'создан'}!
</div>
`;
// Обновляем список идентификаторов
setTimeout(() => {
closeIdUserModal();
loadIdUsers();
}, 1500);
} catch (error) {
console.error('Ошибка сохранения идентификатора:', error);
document.getElementById('iduserMessage').innerHTML = `
<div class="error">
<i class="fas fa-exclamation-circle"></i>
Ошибка: ${error.message}
</div>
`;
}
}
// Подтверждение удаления идентификатора
function confirmDeleteIdUser(id) {
if (!isAdmin) {
alert('Недостаточно прав');
return;
}
const iduser = idusers.find(i => i.id == id);
if (!iduser) return;
document.getElementById('confirmModalTitle').textContent = 'Удаление идентификатора';
document.getElementById('confirmMessage').textContent = `Вы уверены, что хотите удалить идентификатор "${iduser.external_id}" пользователя "${iduser.user_name}"?`;
deleteCallback = deleteIdUser;
deleteParams = { id };
document.getElementById('confirmModal').classList.add('active');
}
// Удаление идентификатора
async function deleteIdUser(params) {
try {
const response = await fetch(`/api2/idusers/${params.id}`, {
method: 'DELETE'
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error || 'Ошибка удаления');
}
const result = await response.json();
if (result.success) {
// Показываем сообщение об успехе
alert('Идентификатор успешно удален');
// Обновляем список идентификаторов
loadIdUsers();
} else {
throw new Error(result.message || 'Ошибка удаления');
}
} catch (error) {
console.error('Ошибка удаления идентификатора:', error);
alert('Ошибка удаления идентификатора: ' + error.message);
}
}
// Пагинация
function renderPagination(type, totalPages) {
const paginationDiv = document.getElementById(`${type}Pagination`);
if (totalPages <= 1) {
paginationDiv.innerHTML = '';
return;
}
let html = '';
// Кнопка "Назад"
html += `<button class="page-btn" ${currentPage[type] === 1 ? 'disabled' : ''} onclick="changePage('${type}', ${currentPage[type] - 1})">
<i class="fas fa-chevron-left"></i>
</button>`;
// Номера страниц
for (let i = 1; i <= totalPages; i++) {
if (i === 1 || i === totalPages || (i >= currentPage[type] - 2 && i <= currentPage[type] + 2)) {
html += `<button class="page-btn ${currentPage[type] === i ? 'active' : ''}" onclick="changePage('${type}', ${i})">
${i}
</button>`;
} else if (i === currentPage[type] - 3 || i === currentPage[type] + 3) {
html += `<span class="page-btn" style="border: none; background: none;">...</span>`;
}
}
// Кнопка "Вперед"
html += `<button class="page-btn" ${currentPage[type] === totalPages ? 'disabled' : ''} onclick="changePage('${type}', ${currentPage[type] + 1})">
<i class="fas fa-chevron-right"></i>
</button>`;
// Информация о странице
html += `<span style="margin-left: 20px; color: #718096;">
Страница ${currentPage[type]} из ${totalPages}
</span>`;
paginationDiv.innerHTML = html;
}
// Изменение страницы
function changePage(type, page) {
currentPage[type] = page;
if (type === 'groups') {
filterGroups();
} else if (type === 'idusers') {
filterIdUsers();
}
}
// Подтверждение удаления
function confirmDelete() {
if (deleteCallback && deleteParams) {
deleteCallback(deleteParams);
}
closeConfirmModal();
}
// Закрытие модального окна подтверждения
function closeConfirmModal() {
document.getElementById('confirmModal').classList.remove('active');
deleteCallback = null;
deleteParams = null;
}
// Просмотр метаданных
function showMetadata(metadata) {
document.getElementById('metadataContent').textContent = metadata;
document.getElementById('metadataModal').classList.add('active');
}
// Закрытие модального окна метаданных
function closeMetadataModal() {
document.getElementById('metadataModal').classList.remove('active');
}
// Выход из системы
async function logout() {
try {
await fetch('/api/logout', {
method: 'POST'
});
window.location.href = '/';
} catch (error) {
console.error('Ошибка выхода:', error);
window.location.href = '/';
}
}
// Вспомогательные функции
function formatDate(dateString, type = 'date') {
if (!dateString) return '-';
const date = new Date(dateString);
if (type === 'date') {
return date.toLocaleDateString('ru-RU', {
year: 'numeric',
month: '2-digit',
day: '2-digit'
}) + ' ' + date.toLocaleTimeString('ru-RU', {
hour: '2-digit',
minute: '2-digit'
});
} else if (type === 'time') {
return date.toLocaleTimeString('ru-RU', {
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
}
return date.toLocaleString('ru-RU');
}
function getServiceTypeName(type) {
switch(type) {
case 'sberbank': return 'Сбербанк';
case 'yandex': return 'Яндекс';
case 'ldap': return 'LDAP';
default: return 'Прочие';
}
}
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}