// main.js - Главный файл инициализации window.currentTaskView = 'all'; // 'all', 'my_assigned', 'assigned_to_me' // прикрепляет переменную к объекту window и использует существующее значение, если оно уже есть // Кэш всех задач // let allTasksCache = []; // Повторное выполнение window.allTasksCache = window.allTasksCache || []; document.addEventListener('DOMContentLoaded', function() { checkAuth(); setupEventListeners(); // Инициализация выбора времени initializeTimeSelectors(); // Инициализация фильтра const taskViewFilter = document.getElementById('task-view-filter'); if (taskViewFilter) { taskViewFilter.value = currentTaskView; } // По умолчанию показываем секцию задач showSection('tasks'); }); function setupEventListeners() { // Форма входа const loginForm = document.getElementById('login-form'); if (loginForm && !loginForm._hasSubmitListener) { loginForm.addEventListener('submit', login); loginForm._hasSubmitListener = true; } // Форма создания задачи const createForm = document.getElementById('create-task-form'); if (createForm && !createForm._hasSubmitListener) { createForm.addEventListener('submit', createTask); createForm._hasSubmitListener = true; } // Форма редактирования задачи const editForm = document.getElementById('edit-task-form'); if (editForm && !editForm._hasSubmitListener) { editForm.addEventListener('submit', updateTask); editForm._hasSubmitListener = true; } // Форма копирования задачи const copyForm = document.getElementById('copy-task-form'); if (copyForm && !copyForm._hasSubmitListener) { copyForm.addEventListener('submit', copyTask); copyForm._hasSubmitListener = true; } // Форма редактирования назначения const editAssignmentForm = document.getElementById('edit-assignment-form'); if (editAssignmentForm && !editAssignmentForm._hasSubmitListener) { editAssignmentForm.addEventListener('submit', updateAssignment); editAssignmentForm._hasSubmitListener = true; } // Форма доработки const reworkForm = document.getElementById('rework-task-form'); if (reworkForm && !reworkForm._hasSubmitListener) { reworkForm.addEventListener('submit', sendForRework); reworkForm._hasSubmitListener = true; } // Файлы const filesInput = document.getElementById('files'); if (filesInput && !filesInput._hasChangeListener) { filesInput.addEventListener('change', updateFileList); filesInput._hasChangeListener = true; } const editFilesInput = document.getElementById('edit-files'); if (editFilesInput && !editFilesInput._hasChangeListener) { editFilesInput.addEventListener('change', updateEditFileList); editFilesInput._hasChangeListener = true; } // Настройки уведомлений const notificationForm = document.getElementById('notification-settings-form'); if (notificationForm && !notificationForm._hasSubmitListener) { notificationForm.addEventListener('submit', saveNotificationSettings); notificationForm._hasSubmitListener = true; } // Ознакомление const acquaintanceForm = document.getElementById('acquaintance-task-form'); if (acquaintanceForm && !acquaintanceForm._hasSubmitListener) { acquaintanceForm.addEventListener('submit', createAcquaintanceTask); acquaintanceForm._hasSubmitListener = true; } // Инициализация загрузки файлов initializeFileUploads(); } // Функция для изменения вида задач function changeTaskView() { const select = document.getElementById('task-view-filter'); currentTaskView = select.value; loadTasks(); } // Переопределяем функцию loadTasks для фильтрации (function() { // Сохраняем оригинальную функцию loadTasks const originalLoadTasks = window.loadTasks; // Создаем новую функцию window.loadTasks = async function() { // Вызываем оригинальную функцию if (typeof originalLoadTasks === 'function') { await originalLoadTasks(); } // Кэшируем все задачи if (window.tasks && Array.isArray(window.tasks)) { allTasksCache = [...window.tasks]; // Фильтруем задачи в зависимости от выбранного вида if (currentTaskView !== 'all' && currentUser) { let filteredTasks = []; if (currentTaskView === 'my_assigned') { // Показываем задачи, которые я назначил (я - создатель) filteredTasks = window.tasks.filter(task => { return parseInt(task.created_by) === currentUser.id; }); } else if (currentTaskView === 'assigned_to_me') { // Показываем задачи, назначенные мне (я - исполнитель) filteredTasks = window.tasks.filter(task => { // Проверяем, назначена ли задача текущему пользователю if (task.assignments && Array.isArray(task.assignments)) { return task.assignments.some(assignment => parseInt(assignment.user_id) === currentUser.id ); } return false; }); } // Обновляем глобальный массив задач window.tasks = filteredTasks; // Перерисовываем задачи if (window.renderTasks && typeof window.renderTasks === 'function') { window.renderTasks(); } } } }; })(); // Обновленная функция для создания задачи async function createTask(event) { event.preventDefault(); if (!currentUser) { alert('Требуется аутентификация'); return; } const title = document.getElementById('title').value; let description = document.getElementById('description').value; const taskType = document.getElementById('task-type').value; // Для типа it добавляем кабинет и тип проблемы в описание if (taskType === 'it') { const cabinet = document.getElementById('it-cabinet').value.trim(); const corpusType = document.getElementById('it-corpus-type').value; const problemType = document.getElementById('it-problem-type').value; if (!cabinet || !problemType) { alert('Для заявки в ИТ необходимо указать номер кабинета и тип проблемы'); return; } // Добавляем в конец описания с переносом строки description = description + '
Кабинет: ' + cabinet + '
Корпус: ' + corpusType + '
Тип проблемы: ' + problemType; } // Получаем полную дату и время из отдельных полей const fullDateTime = getFullDateTime('due-date', 'due-time'); if (!title || !fullDateTime) { alert('Название задачи и дата выполнения обязательны'); return; } if (selectedUsers.length === 0) { alert('Выберите хотя бы одного исполнителя'); return; } // Дополнительная проверка для задач типа "document" if (taskType === 'document' && selectedUsers.length > 0) { // Проверяем, что все выбранные пользователи - секретари for (const userId of selectedUsers) { const groups = await getUserGroups(userId); const hasSecretaryGroup = groups.some(group => group.name === 'Секретарь' || (typeof group === 'string' && group.includes('Секретарь')) ); if (!hasSecretaryGroup) { alert('Для задач типа "Согласование документа" можно выбирать только пользователей с правом "согласовать документы"'); return; } } } // Дополнительная проверка для задач типа "it" if (taskType === 'it' && selectedUsers.length > 0) { // Проверяем, что все выбранные пользователи - it for (const userId of selectedUsers) { const groups = await getUserGroups(userId); const hasSecretaryGroup = groups.some(group => group.name === 'ИТ специалист' || (typeof group === 'string' && group.includes('ИТ специалист')) ); if (!hasSecretaryGroup) { alert('Для задачи можно выбирать только пользователей из группы "ИТ специалист"'); return; } } } // Дополнительная проверка для задач типа "ahch" if (taskType === 'ahch' && selectedUsers.length > 0) { // Проверяем, что все выбранные пользователи - it for (const userId of selectedUsers) { const groups = await getUserGroups(userId); const hasSecretaryGroup = groups.some(group => group.name === 'АХЧ' || (typeof group === 'string' && group.includes('АХЧ')) ); if (!hasSecretaryGroup) { alert('Для задачи можно выбирать только пользователей из группы "сотрудники АХЧ"'); return; } } } // Дополнительная проверка для задач типа "psychologist" if (taskType === 'psychologist' && selectedUsers.length > 0) { // Проверяем, что все выбранные пользователи - it for (const userId of selectedUsers) { const groups = await getUserGroups(userId); const hasSecretaryGroup = groups.some(group => group.name === 'психолог' || (typeof group === 'string' && group.includes('психолог')) ); if (!hasSecretaryGroup) { alert('Для задачи можно выбирать только пользователей из группы "сотрудники психологи"'); return; } } } // Дополнительная проверка для задач типа "speech_therapist" if (taskType === 'speech_therapist' && selectedUsers.length > 0) { // Проверяем, что все выбранные пользователи - speech_therapist for (const userId of selectedUsers) { const groups = await getUserGroups(userId); const hasSecretaryGroup = groups.some(group => group.name === 'логопед' || (typeof group === 'string' && group.includes('логопед')) ); if (!hasSecretaryGroup) { alert('Для задачи можно выбирать только пользователей из группы "сотрудники логопеды"'); return; } } } // Дополнительная проверка для задач типа "hr" if (taskType === 'hr' && selectedUsers.length > 0) { // Проверяем, что все выбранные пользователи - hr for (const userId of selectedUsers) { const groups = await getUserGroups(userId); const hasSecretaryGroup = groups.some(group => group.name === 'Диспетчер' || (typeof group === 'string' && group.includes('Диспетчер')) ); if (!hasSecretaryGroup) { alert('Для задачи можно выбирать только пользователей из группы "Диспетчер расписания"'); return; } } } // Дополнительная проверка для задач типа "certificate" if (taskType === 'certificate' && selectedUsers.length > 0) { // Проверяем, что все выбранные пользователи - certificate for (const userId of selectedUsers) { const groups = await getUserGroups(userId); const hasSecretaryGroup = groups.some(group => group.name === 'Администрация' || (typeof group === 'string' && group.includes('Администрация')) ); if (!hasSecretaryGroup) { alert('Для задачи можно выбирать только пользователей из группы "секретари и завучи"'); return; } } } // Дополнительная проверка для задач типа "e_journal" if (taskType === 'e_journal' && selectedUsers.length > 0) { // Проверяем, что все выбранные пользователи - e_journal for (const userId of selectedUsers) { const groups = await getUserGroups(userId); const hasSecretaryGroup = groups.some(group => group.name === 'Админ ЭЖ' || (typeof group === 'string' && group.includes('Админ ЭЖ')) ); if (!hasSecretaryGroup) { alert('Для задачи можно выбирать только пользователей из группы "администраторы электронного журнала"'); return; } } } // Дополнительная проверка для задач типа "Social_educator" if (taskType === 'Social_educator' && selectedUsers.length > 0) { // Проверяем, что все выбранные пользователи - Social_educator for (const userId of selectedUsers) { const groups = await getUserGroups(userId); const hasSecretaryGroup = groups.some(group => group.name === 'Социальный педагог' || (typeof group === 'string' && group.includes('Социальный педагог')) ); if (!hasSecretaryGroup) { alert('Для задачи можно выбирать только пользователей из группы "Социальный педагог"'); return; } } } const formData = new FormData(); formData.append('title', title); formData.append('description', description); formData.append('taskType', taskType); formData.append('dueDate', fullDateTime); selectedUsers.forEach(userId => { formData.append('assignedUsers', userId); }); const files = document.getElementById('files').files; for (let i = 0; i < files.length; i++) { formData.append('files', files[i]); } // Проверка прав для типа "regular" const userGroups = currentUser?.groups || []; const isAdmin = currentUser?.role === 'admin'; const hasTasksGroup = currentUser?.role === 'tasks'; const hasSecretaryGroup = currentUser?.role === 'secretary'; if (taskType === 'regular' && !(isAdmin || hasTasksGroup || hasSecretaryGroup)) { alert('У вас нет прав для создания обычных задач. Выберите другой тип задачи.'); return; } try { const response = await fetch('/api/tasks', { method: 'POST', body: formData }); if (response.ok) { alert('Задача успешно создана!'); // Сброс формы document.getElementById('create-task-form').reset(); document.getElementById('file-list').innerHTML = ''; document.getElementById('user-search').value = ''; selectedUsers = []; // Сбрасываем дату и время const tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); document.getElementById('due-date').value = tomorrow.toISOString().split('T')[0]; document.getElementById('due-time').value = '12:00'; // Сбрасываем активные кнопки const timeButtons = document.querySelectorAll('.time-btn'); timeButtons.forEach(btn => btn.classList.remove('active')); if (timeButtons.length > 0) { timeButtons[0].classList.add('active'); } // Обновляем отображение кнопок updateDateTimeDisplay(); // Обновляем список пользователей renderUsersChecklist(); // Загружаем задачи и логи loadTasks(); loadActivityLogs(); // Показываем секцию задач showSection('tasks'); } else { const error = await response.json(); alert(error.error || 'Ошибка создания задачи'); } } catch (error) { console.error('Ошибка:', error); alert('Ошибка создания задачи'); } } // Обновленная функция открытия модального окна редактирования async function openEditModal(taskId) { try { const response = await fetch(`/api/tasks/${taskId}`); if (!response.ok) { if (response.status === 404) { alert('Задача не найдена или у вас нет прав доступа'); } throw new Error('Ошибка загрузки задачи'); } const task = await response.json(); if (!canUserEditTask(task)) { alert('У вас нет прав для редактирования этой задачи'); return; } document.getElementById('edit-task-id').value = task.id; document.getElementById('edit-title').value = task.title; document.getElementById('edit-description').value = task.description || ''; // Устанавливаем дату и время с помощью новой функции setDateTimeForEdit(task.due_date); // Устанавливаем выбранных пользователей editSelectedUsers = task.assignments ? task.assignments.map(a => a.user_id) : []; renderEditUsersChecklist(users); // Показываем существующие файлы currentEditTaskFiles = task.files || []; updateEditFileList(); document.getElementById('edit-task-modal').style.display = 'block'; } catch (error) { console.error('Ошибка:', error); alert('Ошибка загрузки задачи'); } } // Обновленная функция обновления задачи async function updateTask(event) { event.preventDefault(); const taskId = document.getElementById('edit-task-id').value; const title = document.getElementById('edit-title').value; const description = document.getElementById('edit-description').value; // Получаем полную дату и время из отдельных полей const fullDateTime = getFullDateTime('edit-due-date', 'edit-due-time'); if (!fullDateTime) { alert('Дата и время выполнения обязательны'); return; } // Используем editSelectedUsers const assignedUserIds = editSelectedUsers; const formData = new FormData(); formData.append('title', title); formData.append('description', description); formData.append('assignedUsers', JSON.stringify(assignedUserIds)); formData.append('dueDate', fullDateTime); const files = document.getElementById('edit-files').files; for (let i = 0; i < files.length; i++) { formData.append('files', files[i]); } try { const response = await fetch(`/api/tasks/${taskId}`, { method: 'PUT', body: formData }); if (response.ok) { alert('Задача успешно обновлена!'); closeEditModal(); loadTasks(); loadActivityLogs(); } else { const error = await response.json(); alert(error.error || 'Ошибка обновления задачи'); } } catch (error) { console.error('Ошибка:', error); alert('Ошибка обновления задачи'); } } // Обновленная функция создания копии задачи async function copyTask(event) { event.preventDefault(); const taskId = document.getElementById('copy-task-id').value; // Получаем полную дату и время из отдельных полей const fullDateTime = getFullDateTime('copy-due-date', 'copy-due-time'); if (!fullDateTime) { alert('Дата и время выполнения обязательны для копии задачи'); return; } // Используем copySelectedUsers const assignedUserIds = copySelectedUsers; if (assignedUserIds.length === 0) { alert('Выберите хотя бы одного исполнителя для копии задачи'); return; } try { const response = await fetch(`/api/tasks/${taskId}/copy`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ assignedUsers: assignedUserIds, dueDate: fullDateTime }) }); if (response.ok) { alert('Копия задачи успешно создана!'); closeCopyModal(); loadTasks(); loadActivityLogs(); } else { const error = await response.json(); alert(error.error || 'Ошибка создания копии задачи'); } } catch (error) { console.error('Ошибка:', error); alert('Ошибка создания копии задачи'); } } // Функция для отображения секции function showSection(sectionName) { document.querySelectorAll('.section').forEach(section => { section.classList.remove('active'); }); document.getElementById(sectionName + '-section').classList.add('active'); if (sectionName === 'tasks') { loadTasks(); } else if (sectionName === 'logs') { loadActivityLogs(); } else if (sectionName === 'kanban') { loadKanbanTasks(); } // Загрузка профиля при переходе в личный кабинет if (sectionName === 'profile') { loadUserProfile(); loadNotificationSettings(); } if (sectionName === 'reports') { if (typeof loadReportData === 'function') { loadReportData(); } } } // Функция для отображения Канбан доски function showKanbanSection() { showSection('kanban'); } window.setupEventListeners = setupEventListeners;