поправил добавление дисциплин и расписание занятий

This commit is contained in:
Zuev
2026-05-31 14:42:43 +03:00
parent e989391c8d
commit e2a3553a09
4 changed files with 77 additions and 36 deletions

View File

@@ -289,6 +289,25 @@
grid-template-columns: repeat(8, minmax(125px, 1fr)) auto;
}
.subject-import-rows-list {
display: flex;
flex-direction: column;
gap: 0.75rem;
margin-top: 0.75rem;
overflow: visible;
}
.subject-import-row {
display: grid;
grid-template-columns: minmax(120px, 1fr) minmax(200px, 3fr) auto;
gap: 0.75rem;
align-items: end;
padding: 0.75rem;
background: var(--bg-input);
border: 1px solid var(--bg-card-border);
border-radius: var(--radius-sm);
}
.schedule-rule-actions {
margin-top: 0.25rem;
clear: both;
@@ -1259,6 +1278,10 @@
grid-template-columns: 1fr;
}
.subject-import-row {
grid-template-columns: 1fr;
}
.calendar-fill-panel {
grid-template-columns: 1fr;
}

View File

@@ -12,6 +12,8 @@ export async function initDepartmentWorkspace() {
const endInput = document.getElementById('department-workspace-end');
const refreshButton = document.getElementById('department-workspace-refresh');
const importForm = document.getElementById('department-subject-import-form');
const importRowsContainer = document.getElementById('subject-import-rows');
const importAddButton = document.getElementById('subject-import-add');
const subjectsTbody = document.getElementById('department-subjects-tbody');
const subjectCount = document.getElementById('department-subject-count');
const commentsCard = document.getElementById('department-comments-card');
@@ -32,6 +34,15 @@ export async function initDepartmentWorkspace() {
startInput?.addEventListener('change', handleStartDateChange);
endInput?.addEventListener('change', loadWorkload);
importForm?.addEventListener('submit', importSubjects);
importAddButton?.addEventListener('click', () => renderImportRows([...readImportRows(), { code: '', name: '' }]));
importRowsContainer?.addEventListener('click', (event) => {
const removeBtn = event.target.closest('.subject-import-remove');
if (removeBtn) {
const rows = readImportRows();
rows.splice(Number(removeBtn.dataset.index), 1);
renderImportRows(rows.length ? rows : [{ code: '', name: '' }]);
}
});
commentsForm?.addEventListener('submit', saveComment);
commentsCloseButton?.addEventListener('click', () => {
commentsCard.hidden = true;
@@ -50,6 +61,7 @@ export async function initDepartmentWorkspace() {
departmentField.hidden = true;
departmentSelect.value = userDepartmentId || '';
}
renderImportRows([{ code: '', name: '' }]);
await loadWorkspace();
} catch (error) {
showAlert('department-workspace-alert', error.message || 'Ошибка загрузки кабинета кафедры', 'error');
@@ -96,38 +108,57 @@ export async function initDepartmentWorkspace() {
}
}
function renderImportRows(rows) {
if (!importRowsContainer) return;
importRowsContainer.innerHTML = (rows || [{ code: '', name: '' }]).map((row, index) => `
<div class="subject-import-row" data-index="${index}">
<div class="form-group">
<label>Код</label>
<input type="text" class="subject-import-code" value="${escapeHtml(row.code || '')}" placeholder="DB201">
</div>
<div class="form-group">
<label>Название</label>
<input type="text" class="subject-import-name" value="${escapeHtml(row.name || '')}" placeholder="Базы данных">
</div>
<button type="button" class="btn-delete subject-import-remove" data-index="${index}">Удалить</button>
</div>
`).join('');
}
function readImportRows() {
if (!importRowsContainer) return [];
return Array.from(importRowsContainer.querySelectorAll('.subject-import-row')).map(row => ({
code: (row.querySelector('.subject-import-code')?.value || '').trim(),
name: (row.querySelector('.subject-import-name')?.value || '').trim()
}));
}
async function importSubjects(event) {
event.preventDefault();
const alertId = 'department-subject-import-alert';
hideAlert(alertId);
const departmentId = selectedDepartmentId();
const rows = document.getElementById('department-subject-import-text').value
.split('\n')
.map(row => row.trim())
.filter(Boolean)
.map(row => {
const [code, ...nameParts] = row.split(';');
return {
code: (code || '').trim(),
name: nameParts.join(';').trim(),
const rows = readImportRows()
.filter(item => item.name)
.map(item => ({
code: item.code,
name: item.name,
departmentId: Number(departmentId)
};
})
.filter(item => item.name);
}));
if (!departmentId) {
showAlert(alertId, 'Выберите кафедру', 'error');
return;
}
if (!rows.length) {
showAlert(alertId, 'Добавьте хотя бы одну строку в формате «код; название»', 'error');
showAlert(alertId, 'Заполните название хотя бы одной дисциплины', 'error');
return;
}
try {
const result = await api.post('/api/department/subjects/import', rows);
showAlert(alertId, result.message || 'Дисциплины загружены', 'success');
document.getElementById('department-subject-import-text').value = '';
renderImportRows([{ code: '', name: '' }]);
await loadSubjects();
} catch (error) {
showAlert(alertId, error.message || 'Ошибка загрузки дисциплин', 'error');

View File

@@ -416,9 +416,7 @@ export async function initSchedule() {
if (!lessons.length) return '';
const oddLessons = lessons.filter(lesson => lesson.parity === 'BOTH' || lesson.parity === 'ODD');
const evenLessons = lessons.filter(lesson => lesson.parity === 'BOTH' || lesson.parity === 'EVEN');
const shouldSplit = oddLessons.length > 0
&& evenLessons.length > 0
&& visualLessonSignature(oddLessons) !== visualLessonSignature(evenLessons);
const shouldSplit = lessons.some(l => l.parity !== 'BOTH');
if (!shouldSplit) {
return `<div class="schedule-visual-unified">${uniqueVisualLessons(lessons).map(renderVisualLesson).join('')}</div>`;
@@ -1111,21 +1109,7 @@ export async function initSchedule() {
function compactWeekRanges(weeks) {
const uniqueWeeks = [...new Set((weeks || []).map(Number).filter(Boolean))].sort((a, b) => a - b);
if (!uniqueWeeks.length) return '';
const ranges = [];
let start = uniqueWeeks[0];
let previous = uniqueWeeks[0];
for (let index = 1; index < uniqueWeeks.length; index += 1) {
const week = uniqueWeeks[index];
if (week === previous + 1) {
previous = week;
continue;
}
ranges.push(weekRangeText(start, previous));
start = week;
previous = week;
}
ranges.push(weekRangeText(start, previous));
return `(${ranges.join(', ')})`;
return `(${weekRangeText(uniqueWeeks[0], uniqueWeeks[uniqueWeeks.length - 1])})`;
}
function weekRangeText(start, end) {

View File

@@ -30,9 +30,12 @@
<h2>Загрузка дисциплин</h2>
</div>
<form id="department-subject-import-form" class="stack-form">
<div class="form-group">
<label for="department-subject-import-text">Строки в формате «код; название»</label>
<textarea id="department-subject-import-text" rows="8" placeholder="DB201; Базы данных&#10;AI101; Искусственный интеллект"></textarea>
<div class="subject-import-slots-panel">
<div class="card-header-row">
<label class="schedule-section-label" style="margin:0">Дисциплины для загрузки</label>
<button type="button" class="btn-edit-classroom" id="subject-import-add">Добавить строку</button>
</div>
<div id="subject-import-rows" class="subject-import-rows-list"></div>
</div>
<button type="submit" class="btn-primary">Загрузить</button>
<div class="form-alert" id="department-subject-import-alert" role="alert"></div>