/
erioxis
/
web-nodejs
Обзор
Документация
Войти
/
erioxis
/
web-nodejs
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
public/lab10/task2/script.js
859 строк
32 KB
erioxis
lab11fix
15 дек 2025, 23:21
15 дек 2025, 23:21
70dc7ba
Код
Авторство
О чём код?
// public/lab10/task2/script.js let allGroups = []; let allTeachers = []; let allDisciplines = []; let allRooms = []; function showContent(contentId) { document.querySelectorAll('.content').forEach(el => el.classList.remove('active')); document.getElementById(contentId).classList.add('active'); // При открытии вкладки "Просмотр расписания" загружаем справочники для фильтров if (contentId === 'schedule-view') { loadScheduleDataForView(); } // При открытии вкладки "Управление данными" загружаем все данные if (contentId === 'data-management') { loadAllData(); } } function switchTab(tabId) { document.querySelectorAll('.tab-content').forEach(el => el.classList.remove('active')); document.querySelectorAll('.tab').forEach(el => el.classList.remove('active')); document.getElementById(tabId).classList.add('active'); document.querySelector(`.tab[onclick="switchTab('${tabId}')"]`).classList.add('active'); // Загрузить данные для выбранного таба if (tabId === 'groups-tab') { loadGroups(); } else if (tabId === 'teachers-tab') { loadTeachers(); } else if (tabId === 'disciplines-tab') { loadDisciplines(); } else if (tabId === 'rooms-tab') { loadRooms(); } else if (tabId === 'schedule-tab') { loadScheduleRecords(); // Загружаем справочники для заполнения форм в табе расписания populateDropdowns(); } } // --- Загрузка данных --- async function loadScheduleDataForView() { // Загружаем справочники СНАЧАЛА, чтобы заполнить фильтры await Promise.all([ loadGroupsForFilters(), loadTeachersForFilters(), loadDisciplinesForFilters(), loadRoomsForFilters() ]); // Затем загружаем расписание await loadSchedule(); } async function loadAllData() { await Promise.all([ loadGroups(), loadTeachers(), loadDisciplines(), loadRooms(), loadScheduleRecords() ]); // Загружаем справочники для заполнения форм в табе расписания populateDropdowns(); } // --- Функции загрузки справочников для фильтров (Задание 2) --- async function loadGroupsForFilters() { try { const response = await fetch('/api/lab10/task2/groups'); const groups = await response.json(); populateSelect('group-filter', groups, 'id', 'name', 'Все группы'); } catch (error) { console.error('Ошибка при загрузке групп для фильтра:', error); populateSelect('group-filter', [], 'id', 'name', 'Все группы'); } } async function loadTeachersForFilters() { try { const response = await fetch('/api/lab10/task2/teachers'); const teachers = await response.json(); populateSelect('teacher-filter', teachers, 'id', 'full_name', 'Все преподаватели'); } catch (error) { console.error('Ошибка при загрузке преподавателей для фильтра:', error); populateSelect('teacher-filter', [], 'id', 'full_name', 'Все преподаватели'); } } async function loadDisciplinesForFilters() { try { const response = await fetch('/api/lab10/task2/disciplines'); const disciplines = await response.json(); populateSelect('discipline-filter', disciplines, 'id', 'name', 'Все дисциплины'); } catch (error) { console.error('Ошибка при загрузке дисциплин для фильтра:', error); populateSelect('discipline-filter', [], 'id', 'name', 'Все дисциплины'); } } async function loadRoomsForFilters() { try { const response = await fetch('/api/lab10/task2/rooms'); const rooms = await response.json(); populateSelect('room-filter', rooms, 'id', 'name', 'Все аудитории'); } catch (error) { console.error('Ошибка при загрузке аудиторий для фильтра:', error); populateSelect('room-filter', [], 'id', 'name', 'Все аудитории'); } } // --- Функции загрузки справочников для форм управления (Задание 2) --- async function populateDropdowns() { // Заполняем выпадающие списки для формы добавления/редактирования расписания await Promise.all([ loadGroupsForForm(), loadTeachersForForm(), loadDisciplinesForForm(), loadRoomsForForm() ]); } async function loadGroupsForForm() { try { const response = await fetch('/api/lab10/task2/groups'); allGroups = await response.json(); populateSelect('schedule-group-id', allGroups, 'id', 'name', 'Выберите группу'); } catch (error) { console.error('Ошибка при загрузке групп для формы:', error); populateSelect('schedule-group-id', [], 'id', 'name', 'Выберите группу'); } } async function loadTeachersForForm() { try { const response = await fetch('/api/lab10/task2/teachers'); allTeachers = await response.json(); populateSelect('schedule-teacher-id', allTeachers, 'id', 'full_name', 'Выберите преподавателя'); } catch (error) { console.error('Ошибка при загрузке преподавателей для формы:', error); populateSelect('schedule-teacher-id', [], 'id', 'full_name', 'Выберите преподавателя'); } } async function loadDisciplinesForForm() { try { const response = await fetch('/api/lab10/task2/disciplines'); allDisciplines = await response.json(); populateSelect('schedule-discipline-id', allDisciplines, 'id', 'name', 'Выберите дисциплину'); } catch (error) { console.error('Ошибка при загрузке дисциплин для формы:', error); populateSelect('schedule-discipline-id', [], 'id', 'name', 'Выберите дисциплину'); } } async function loadRoomsForForm() { try { const response = await fetch('/api/lab10/task2/rooms'); allRooms = await response.json(); populateSelect('schedule-room-id', allRooms, 'id', 'name', 'Выберите аудиторию'); } catch (error) { console.error('Ошибка при загрузке аудиторий для формы:', error); populateSelect('schedule-room-id', [], 'id', 'name', 'Выберите аудиторию'); } } // --- Универсальная функция для заполнения <select> --- function populateSelect(elementId, data, valueField, textField, defaultOptionText) { const select = document.getElementById(elementId); // Очищаем список, но оставляем первую опцию (defaultOptionText) select.innerHTML = `<option value="">${defaultOptionText}</option>`; data.forEach(item => { const option = document.createElement('option'); option.value = item[valueField]; option.textContent = item[textField]; select.appendChild(option); }); } // --- Загрузка данных для отображения в табах управления (Задание 2) --- async function loadGroups() { showLoading('groups-list'); try { const response = await fetch('/api/lab10/task2/groups'); const groups = await response.json(); displayGroups(groups); } catch (error) { showError('groups-list', 'Ошибка при загрузке групп: ' + error.message); } } async function loadTeachers() { showLoading('teachers-list'); try { const response = await fetch('/api/lab10/task2/teachers'); const teachers = await response.json(); displayTeachers(teachers); } catch (error) { showError('teachers-list', 'Ошибка при загрузке преподавателей: ' + error.message); } } async function loadDisciplines() { showLoading('disciplines-list'); try { const response = await fetch('/api/lab10/task2/disciplines'); const disciplines = await response.json(); displayDisciplines(disciplines); } catch (error) { showError('disciplines-list', 'Ошибка при загрузке дисциплин: ' + error.message); } } async function loadRooms() { showLoading('rooms-list'); try { const response = await fetch('/api/lab10/task2/rooms'); const rooms = await response.json(); displayRooms(rooms); } catch (error) { showError('rooms-list', 'Ошибка при загрузке аудиторий: ' + error.message); } } async function loadScheduleRecords() { showLoading('schedule-records-list'); try { const response = await fetch('/api/lab10/task2/schedule'); const records = await response.json(); displayScheduleRecords(records); } catch (error) { showError('schedule-records-list', 'Ошибка при загрузке расписания: ' + error.message); } } // --- Отображение данных (Задание 2) --- async function loadSchedule() { const group = document.getElementById('group-filter').value; // Может быть "" или числом const teacher = document.getElementById('teacher-filter').value; const discipline = document.getElementById('discipline-filter').value; const room = document.getElementById('room-filter').value; const day = document.getElementById('day-filter').value; const week = document.getElementById('week-filter').value; showLoading('schedule-result'); try { const params = new URLSearchParams(); if (group && group !== '') params.append('group_id', group); if (teacher && teacher !== '') params.append('teacher_id', teacher); if (discipline && discipline !== '') params.append('discipline_id', discipline); if (room && room !== '') params.append('room_id', room); if (day && day !== '') params.append('day_of_week', day); if (week && week !== '') params.append('week_number', week); const response = await fetch(`/api/lab10/task2/schedule?${params.toString()}`); // Проверяем статус ответа if (!response.ok) { const errorData = await response.json().catch(() => ({ error: 'Неизвестная ошибка' })); throw new Error(errorData.error || `HTTP error! status: ${response.status}`); } const data = await response.json(); displaySchedule(data); } catch (error) { showError('schedule-result', 'Ошибка при загрузке расписания: ' + error.message); } } function displaySchedule(schedule) { const container = document.getElementById('schedule-result'); if (schedule.length === 0) { container.innerHTML = '<div class="error">Расписание не найдено по заданным фильтрам.</div>'; return; } // Создаем массив для сортировки дней недели const dayOrder = ['Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота']; // Сортируем расписание по дню недели (используя индекс из dayOrder), затем по времени начала schedule.sort((a, b) => { const dayAIndex = dayOrder.indexOf(a.day_of_week); const dayBIndex = dayOrder.indexOf(b.day_of_week); if (dayAIndex !== dayBIndex) { return dayAIndex - dayBIndex; // Сначала по дню недели } // Если дни одинаковые, сортируем по времени начала return a.start_time.localeCompare(b.start_time); }); let tableHtml = ` <table class="schedule-table"> <thead> <tr> <th>Неделя</th> <th>День недели</th> <th>Время</th> <th>Группа</th> <th>Преподаватель</th> <th>Дисциплина</th> <th>Аудитория</th> <th>Тип занятия</th> </tr> </thead> <tbody> `; schedule.forEach(item => { tableHtml += ` <tr> <td>${item.week_number}</td> <td>${item.day_of_week}</td> <td>${item.start_time} - ${item.end_time}</td> <td>${item.group_name}</td> <td>${item.teacher_name}</td> <td>${item.discipline_name}</td> <td>${item.room_name}</td> <td>${item.lesson_type}</td> </tr> `; }); tableHtml += ` </tbody> </table> `; container.innerHTML = tableHtml; } function displayGroups(groups) { const container = document.getElementById('groups-list'); let html = `<h4>Список групп (${groups.length})</h4>`; if (groups.length === 0) { html += '<p>Нет данных.</p>'; } else { html += '<ul>'; groups.forEach(group => { html += ` <li> ${group.name} <button onclick="deleteGroup(${group.id})">Удалить</button> </li> `; }); html += '</ul>'; } container.innerHTML = html; } function displayTeachers(teachers) { const container = document.getElementById('teachers-list'); let html = `<h4>Список преподавателей (${teachers.length})</h4>`; if (teachers.length === 0) { html += '<p>Нет данных.</p>'; } else { html += '<ul>'; teachers.forEach(teacher => { html += ` <li> ${teacher.full_name} (${teacher.position}, ${teacher.department}) <button onclick="deleteTeacher(${teacher.id})">Удалить</button> </li> `; }); html += '</ul>'; } container.innerHTML = html; } function displayDisciplines(disciplines) { const container = document.getElementById('disciplines-list'); let html = `<h4>Список дисциплин (${disciplines.length})</h4>`; if (disciplines.length === 0) { html += '<p>Нет данных.</p>'; } else { html += '<ul>'; disciplines.forEach(discipline => { html += ` <li> ${discipline.name} (${discipline.hours} часов) <button onclick="deleteDiscipline(${discipline.id})">Удалить</button> </li> `; }); html += '</ul>'; } container.innerHTML = html; } function displayRooms(rooms) { const container = document.getElementById('rooms-list'); let html = `<h4>Список аудиторий (${rooms.length})</h4>`; if (rooms.length === 0) { html += '<p>Нет данных.</p>'; } else { html += '<ul>'; rooms.forEach(room => { html += ` <li> ${room.name} (${room.building}, вместимость: ${room.capacity}) <button onclick="deleteRoom(${room.id})">Удалить</button> </li> `; }); html += '</ul>'; } container.innerHTML = html; } function displayScheduleRecords(records) { const container = document.getElementById('schedule-records-list'); let html = `<h4>Записи расписания (${records.length})</h4>`; if (records.length === 0) { html += '<p>Нет данных.</p>'; } else { html += '<ul>'; records.forEach(record => { html += ` <li> Неделя: ${record.week_number}, День: ${record.day_of_week}, Время: ${record.start_time} - ${record.end_time}<br> Группа: ${record.group_name}, Преподаватель: ${record.teacher_name}, Дисциплина: ${record.discipline_name}<br> Аудитория: ${record.room_name}, Тип: ${record.lesson_type} <button onclick="editScheduleRecord(${record.id})">Редактировать</button> <button onclick="deleteScheduleRecord(${record.id})">Удалить</button> </li> `; }); html += '</ul>'; } container.innerHTML = html; } // --- Функции управления данными (Задание 2) --- async function addGroup() { const name = document.getElementById('group-name').value.trim(); if (!name) { showError('groups-list', 'Введите название группы'); return; } showLoading('groups-list'); try { const response = await fetch('/api/lab10/task2/groups', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name }) }); const data = await response.json(); if (response.ok) { document.getElementById('group-name').value = ''; await loadGroups(); // Перезагружаем фильтры и формы, где используются группы await loadGroupsForFilters(); await loadGroupsForForm(); } else { showError('groups-list', data.error || 'Не удалось добавить группу'); } } catch (error) { showError('groups-list', 'Ошибка при добавлении группы: ' + error.message); } } async function addTeacher() { const fullName = document.getElementById('teacher-full-name').value.trim(); const position = document.getElementById('teacher-position').value.trim(); const department = document.getElementById('teacher-department').value.trim(); if (!fullName) { showError('teachers-list', 'Введите ФИО преподавателя'); return; } showLoading('teachers-list'); try { const response = await fetch('/api/lab10/task2/teachers', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ full_name: fullName, position, department }) }); const data = await response.json(); if (response.ok) { document.getElementById('teacher-full-name').value = ''; document.getElementById('teacher-position').value = ''; document.getElementById('teacher-department').value = ''; await loadTeachers(); await loadTeachersForFilters(); await loadTeachersForForm(); } else { showError('teachers-list', data.error || 'Не удалось добавить преподавателя'); } } catch (error) { showError('teachers-list', 'Ошибка при добавлении преподавателя: ' + error.message); } } async function addDiscipline() { const name = document.getElementById('discipline-name').value.trim(); const hours = parseInt(document.getElementById('discipline-hours').value); if (!name) { showError('disciplines-list', 'Введите название дисциплины'); return; } if (isNaN(hours) || hours < 0) { showError('disciplines-list', 'Введите корректное количество часов'); return; } showLoading('disciplines-list'); try { const response = await fetch('/api/lab10/task2/disciplines', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name, hours }) }); const data = await response.json(); if (response.ok) { document.getElementById('discipline-name').value = ''; document.getElementById('discipline-hours').value = ''; await loadDisciplines(); await loadDisciplinesForFilters(); await loadDisciplinesForForm(); } else { showError('disciplines-list', data.error || 'Не удалось добавить дисциплину'); } } catch (error) { showError('disciplines-list', 'Ошибка при добавлении дисциплины: ' + error.message); } } async function addRoom() { const name = document.getElementById('room-name').value.trim(); const building = document.getElementById('room-building').value.trim(); const capacity = parseInt(document.getElementById('room-capacity').value); if (!name) { showError('rooms-list', 'Введите название аудитории'); return; } if (isNaN(capacity) || capacity < 1) { showError('rooms-list', 'Введите корректную вместимость'); return; } showLoading('rooms-list'); try { const response = await fetch('/api/lab10/task2/rooms', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name, building, capacity }) }); const data = await response.json(); if (response.ok) { document.getElementById('room-name').value = ''; document.getElementById('room-building').value = ''; document.getElementById('room-capacity').value = ''; await loadRooms(); await loadRoomsForFilters(); await loadRoomsForForm(); } else { showError('rooms-list', data.error || 'Не удалось добавить аудиторию'); } } catch (error) { showError('rooms-list', 'Ошибка при добавлении аудитории: ' + error.message); } } async function addScheduleRecord() { const week = parseInt(document.getElementById('schedule-week').value); const day = document.getElementById('schedule-day').value; const start = document.getElementById('schedule-start-time').value; const end = document.getElementById('schedule-end-time').value; // Используем .value, который будет "" или числом const groupId = document.getElementById('schedule-group-id').value; const teacherId = document.getElementById('schedule-teacher-id').value; const disciplineId = document.getElementById('schedule-discipline-id').value; const roomId = document.getElementById('schedule-room-id').value; const type = document.getElementById('schedule-type').value; if (isNaN(week) || week < 1 || week > 52) { showError('schedule-records-list', 'Введите корректный номер недели (1-52)'); return; } if (!day) { showError('schedule-records-list', 'Выберите день недели'); return; } if (!start || !end) { showError('schedule-records-list', 'Укажите время начала и окончания'); return; } if (!groupId) { // Проверяем на пустую строку showError('schedule-records-list', 'Выберите группу'); return; } if (!teacherId) { showError('schedule-records-list', 'Выберите преподавателя'); return; } if (!disciplineId) { showError('schedule-records-list', 'Выберите дисциплину'); return; } if (!roomId) { showError('schedule-records-list', 'Выберите аудиторию'); return; } if (!type) { showError('schedule-records-list', 'Выберите тип занятия'); return; } showLoading('schedule-records-list'); try { const response = await fetch('/api/lab10/task2/schedule', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ week_number: week, day_of_week: day, start_time: start, end_time: end, group_id: parseInt(groupId), // Преобразуем строку в число teacher_id: parseInt(teacherId), discipline_id: parseInt(disciplineId), room_id: parseInt(roomId), type: type }) }); const data = await response.json(); if (response.ok) { // Очистить форму document.getElementById('schedule-week').value = '1'; document.getElementById('schedule-day').value = 'Понедельник'; document.getElementById('schedule-start-time').value = '09:00'; document.getElementById('schedule-end-time').value = '10:30'; document.getElementById('schedule-group-id').value = ''; // Сбрасываем на "Выберите..." document.getElementById('schedule-teacher-id').value = ''; document.getElementById('schedule-discipline-id').value = ''; document.getElementById('schedule-room-id').value = ''; document.getElementById('schedule-type').value = 'Лекция'; await loadScheduleRecords(); // Перезагружаем расписание, если находимся на вкладке просмотра if (document.getElementById('schedule-view').classList.contains('active')) { loadSchedule(); } } else { showError('schedule-records-list', data.error || 'Не удалось добавить запись'); } } catch (error) { showError('schedule-records-list', 'Ошибка при добавлении записи: ' + error.message); } } async function editScheduleRecord(id) { // Для простоты, просто перезагрузим страницу и покажем форму редактирования alert('Редактирование записи с ID: ' + id + '\n\nВ реальном приложении здесь была бы форма для редактирования.'); // В реальном приложении нужно было бы загрузить данные записи и заполнить форму } async function deleteGroup(id) { if (!confirm('Вы уверены, что хотите удалить эту группу?')) { return; } showLoading('groups-list'); try { const response = await fetch(`/api/lab10/task2/groups/${id}`, { method: 'DELETE' }); const data = await response.json(); if (response.ok) { await loadGroups(); await loadGroupsForFilters(); await loadGroupsForForm(); // Перезагружаем расписание, если находимся на вкладке просмотра if (document.getElementById('schedule-view').classList.contains('active')) { loadSchedule(); } } else { showError('groups-list', data.error || 'Не удалось удалить группу'); } } catch (error) { showError('groups-list', 'Ошибка при удалении группы: ' + error.message); } } async function deleteTeacher(id) { if (!confirm('Вы уверены, что хотите удалить этого преподавателя?')) { return; } showLoading('teachers-list'); try { const response = await fetch(`/api/lab10/task2/teachers/${id}`, { method: 'DELETE' }); const data = await response.json(); if (response.ok) { await loadTeachers(); await loadTeachersForFilters(); await loadTeachersForForm(); if (document.getElementById('schedule-view').classList.contains('active')) { loadSchedule(); } } else { showError('teachers-list', data.error || 'Не удалось удалить преподавателя'); } } catch (error) { showError('teachers-list', 'Ошибка при удалении преподавателя: ' + error.message); } } async function deleteDiscipline(id) { if (!confirm('Вы уверены, что хотите удалить эту дисциплину?')) { return; } showLoading('disciplines-list'); try { const response = await fetch(`/api/lab10/task2/disciplines/${id}`, { method: 'DELETE' }); const data = await response.json(); if (response.ok) { await loadDisciplines(); await loadDisciplinesForFilters(); await loadDisciplinesForForm(); if (document.getElementById('schedule-view').classList.contains('active')) { loadSchedule(); } } else { showError('disciplines-list', data.error || 'Не удалось удалить дисциплину'); } } catch (error) { showError('disciplines-list', 'Ошибка при удалении дисциплины: ' + error.message); } } async function deleteRoom(id) { if (!confirm('Вы уверены, что хотите удалить эту аудиторию?')) { return; } showLoading('rooms-list'); try { const response = await fetch(`/api/lab10/task2/rooms/${id}`, { method: 'DELETE' }); const data = await response.json(); if (response.ok) { await loadRooms(); await loadRoomsForFilters(); await loadRoomsForForm(); if (document.getElementById('schedule-view').classList.contains('active')) { loadSchedule(); } } else { showError('rooms-list', data.error || 'Не удалось удалить аудиторию'); } } catch (error) { showError('rooms-list', 'Ошибка при удалении аудитории: ' + error.message); } } async function deleteScheduleRecord(id) { if (!confirm('Вы уверены, что хотите удалить эту запись расписания?')) { return; } showLoading('schedule-records-list'); try { const response = await fetch(`/api/lab10/task2/schedule/${id}`, { method: 'DELETE' }); const data = await response.json(); if (response.ok) { await loadScheduleRecords(); if (document.getElementById('schedule-view').classList.contains('active')) { loadSchedule(); } } else { showError('schedule-records-list', data.error || 'Не удалось удалить запись'); } } catch (error) { showError('schedule-records-list', 'Ошибка при удалении записи: ' + error.message); } } // --- Вспомогательные функции (Задание 2) --- function showError(containerId, message) { document.getElementById(containerId).innerHTML = `<div class="error">${message}</div>`; } function showLoading(containerId) { document.getElementById(containerId).innerHTML = `<div class="loading">Загрузка...</div>`; }