Поправил графики

This commit is contained in:
dipatrik10
2026-08-14 23:41:55 +03:00
parent 491e373cc3
commit d384a43aa2
22 changed files with 627 additions and 131 deletions

View File

@@ -0,0 +1,43 @@
export function preferredScheduleSemester(semesters, date) {
const items = (semesters || [])
.filter(semester => semester?.startDate && semester?.endDate);
const current = items.find(semester =>
semester.startDate <= date && semester.endDate >= date
);
if (current) return current;
const upcoming = items
.filter(semester => semester.startDate > date)
.sort((first, second) => first.startDate.localeCompare(second.startDate));
if (upcoming.length) return upcoming[0];
return items
.filter(semester => semester.endDate < date)
.sort((first, second) => second.endDate.localeCompare(first.endDate))[0] || null;
}
export function defaultSchedulePeriod(semesters, date, durationDays = 14) {
const semester = preferredScheduleSemester(semesters, date);
const startDate = semester && (date < semester.startDate || date > semester.endDate)
? semester.startDate
: date;
const calculatedEnd = addIsoDays(startDate, Math.max(1, durationDays) - 1);
return {
semester,
startDate,
endDate: semester && calculatedEnd > semester.endDate
? semester.endDate
: calculatedEnd
};
}
function addIsoDays(value, days) {
const [year, month, day] = String(value).split('-').map(Number);
const date = new Date(year, month - 1, day);
date.setDate(date.getDate() + days);
return [
date.getFullYear(),
String(date.getMonth() + 1).padStart(2, '0'),
String(date.getDate()).padStart(2, '0')
].join('-');
}

View File

@@ -1,5 +1,6 @@
import { api, getSession } from '../api.js';
import { escapeHtml, formatLocalDate, showAlert, hideAlert } from '../utils.js';
import { defaultSchedulePeriod } from '../schedule-period.js';
const ROLE_DEPARTMENT = 'DEPARTMENT';
@@ -72,6 +73,7 @@ export async function initDepartmentWorkspace() {
departmentField.hidden = true;
departmentSelect.value = userDepartmentId || '';
}
await selectDefaultWorkloadPeriod(startInput, endInput);
await loadAllTeachers();
renderImportRows([{ code: '', name: '' }]);
await loadWorkspace();
@@ -475,6 +477,20 @@ export async function initDepartmentWorkspace() {
}
}
async function selectDefaultWorkloadPeriod(startInput, endInput) {
try {
const semesters = await api.get('/api/schedule/semesters');
const period = defaultSchedulePeriod(
semesters,
formatLocalDate(new Date())
);
startInput.value = period.startDate;
endInput.value = period.endDate;
} catch (_error) {
// Текущий диапазон остаётся безопасным fallback, если справочник семестров недоступен.
}
}
async function loadDepartments(role, userDepartmentId) {
const departments = await api.get('/api/departments');
fillSelect('department-workspace-department', departments, item => item.id, item => item.departmentName, 'Выберите кафедру');

View File

@@ -1,5 +1,6 @@
import { api, getSession } from '../api.js';
import { escapeHtml, showAlert, hideAlert } from '../utils.js';
import { preferredScheduleSemester } from '../schedule-period.js';
import { canEditScheduleOverrides, createScheduleOverridePanel } from './schedule-override-panel.js';
const ROLE_DEPARTMENT = 'DEPARTMENT';
@@ -321,17 +322,7 @@ export async function initScheduleView() {
function buildSectionContext(target) {
const selectedGroupId = target === TARGET_GROUPS ? normalizeId(valueOf('schedule-view-group')) : '';
const selectedDepartmentId = role === ROLE_DEPARTMENT
? userDepartmentId
: (target === TARGET_DEPARTMENTS ? normalizeId(valueOf('schedule-view-department')) : '');
const allowedGroupIds = new Set();
if (selectedGroupId) {
allowedGroupIds.add(selectedGroupId);
} else if (selectedDepartmentId) {
state.dictionaries.groups
.filter(group => String(group.departmentId) === String(selectedDepartmentId))
.forEach(group => allowedGroupIds.add(String(group.id)));
}
const allowedGroupIds = allowedGroupIdsForScheduleTarget(target, selectedGroupId);
return {
selectedGroupId,
selectedGroupName: selectedGroupId ? groupNameById(selectedGroupId) : '',
@@ -801,8 +792,11 @@ export async function initScheduleView() {
function selectCurrentSemester() {
if (!semesterSelect) return;
const currentSemester = findSemesterForDate(state.dictionaries.semesters, dateInput.value);
semesterSelect.value = currentSemester ? String(currentSemester.id) : '';
const preferredSemester = preferredScheduleSemester(
state.dictionaries.semesters,
dateInput.value
);
semesterSelect.value = preferredSemester ? String(preferredSemester.id) : '';
synchronizeDateWithSemester();
updatePeriodLabel();
}
@@ -960,6 +954,12 @@ function buildScheduleSections(lessons, splitType, context) {
.sort((a, b) => naturalCompare(a.title, b.title));
}
export function allowedGroupIdsForScheduleTarget(target, selectedGroupId) {
return target === TARGET_GROUPS && selectedGroupId
? new Set([String(selectedGroupId)])
: new Set();
}
function splitEntitiesForLesson(lesson, splitType, context) {
if (splitType === TARGET_TEACHERS) {
return [singleEntity('teacher', lesson.teacherId, lesson.teacherName, 'Преподаватель не указан')];