задачи 2 и 8
This commit is contained in:
@@ -67,6 +67,9 @@ export async function initSchedule() {
|
||||
const ruleIdInput = document.getElementById('schedule-rule-id');
|
||||
const ruleSubjectSelect = document.getElementById('schedule-rule-subject');
|
||||
const ruleSemesterSelect = document.getElementById('schedule-rule-semester');
|
||||
const scheduleVersionSelect = document.getElementById('schedule-version-select');
|
||||
const scheduleVersionNote = document.getElementById('schedule-version-note');
|
||||
const scheduleVersionManage = document.getElementById('schedule-version-manage');
|
||||
const ruleTypeInputs = Object.fromEntries(LESSON_TYPE_LIMITS.map(config => [config.key, {
|
||||
hours: document.getElementById(config.hoursInputId),
|
||||
startWeek: document.getElementById(config.startWeekInputId)
|
||||
@@ -125,6 +128,7 @@ export async function initSchedule() {
|
||||
let academicYears = [];
|
||||
let semesters = [];
|
||||
let approvedTeacherPreferences = [];
|
||||
let scheduleVersions = [];
|
||||
let selectedVisualYearId = '';
|
||||
let selectedVisualSemesterId = '';
|
||||
let selectedVisualGroupIds = new Set();
|
||||
@@ -139,8 +143,11 @@ export async function initSchedule() {
|
||||
|
||||
try {
|
||||
await Promise.all([loadBaseLists(), loadTimeSlots(), loadYears(), loadApprovedTeacherPreferences()]);
|
||||
await loadScheduleVersions();
|
||||
renderRuleGroups([]);
|
||||
renderRuleSlots([{}]);
|
||||
syncRuleSemesterWithVersion();
|
||||
setRuleEditorEnabled(Boolean(selectedScheduleVersion()));
|
||||
await loadRules();
|
||||
} catch (error) {
|
||||
showAlert('schedule-rule-alert', error.message || 'Ошибка загрузки данных расписания', 'error');
|
||||
@@ -148,6 +155,17 @@ export async function initSchedule() {
|
||||
|
||||
function bindEvents() {
|
||||
refreshRulesButton?.addEventListener('click', loadRules);
|
||||
scheduleVersionSelect?.addEventListener('change', async () => {
|
||||
if (scheduleVersionSelect.value) {
|
||||
localStorage.setItem('magistr.schedule.versionId', scheduleVersionSelect.value);
|
||||
}
|
||||
resetRuleForm();
|
||||
syncRuleSemesterWithVersion();
|
||||
await loadRules();
|
||||
});
|
||||
scheduleVersionManage?.addEventListener('click', () => {
|
||||
document.querySelector('.nav-item[data-tab="schedule-versions"]')?.click();
|
||||
});
|
||||
ruleResetButton?.addEventListener('click', resetRuleForm);
|
||||
slotAddButton?.addEventListener('click', () => renderRuleSlots([...readRuleSlots(false), {}]));
|
||||
visualToggleButton?.addEventListener('click', toggleVisualDrawer);
|
||||
@@ -284,10 +302,62 @@ export async function initSchedule() {
|
||||
updatePreferenceHints();
|
||||
}
|
||||
|
||||
async function loadScheduleVersions() {
|
||||
const responses = await Promise.all(semesters.map(semester =>
|
||||
api.get(`/api/edu-office/schedule/versions?semesterId=${encodeURIComponent(semester.id)}`)
|
||||
));
|
||||
scheduleVersions = responses.flat().filter(version => version.status === 'DRAFT');
|
||||
const storedId = localStorage.getItem('magistr.schedule.versionId');
|
||||
const stored = scheduleVersions.find(version => String(version.id) === storedId);
|
||||
const selected = stored || scheduleVersions[0] || null;
|
||||
scheduleVersionSelect.innerHTML = scheduleVersions.length
|
||||
? scheduleVersions.map(version => `
|
||||
<option value="${version.id}">
|
||||
${escapeHtml(version.semesterLabel)} · v${escapeHtml(String(version.versionNumber))} · ${escapeHtml(version.name)}
|
||||
</option>
|
||||
`).join('')
|
||||
: '<option value="">Черновики не созданы</option>';
|
||||
scheduleVersionSelect.value = selected ? String(selected.id) : '';
|
||||
if (selected) {
|
||||
localStorage.setItem('magistr.schedule.versionId', String(selected.id));
|
||||
scheduleVersionNote.textContent = `Версия ${selected.versionNumber} · ${selected.name}. Изменения не видны пользователям до публикации.`;
|
||||
} else {
|
||||
scheduleVersionNote.textContent = 'Черновика нет. Создайте его в разделе «Версии расписания».';
|
||||
}
|
||||
setRuleEditorEnabled(Boolean(selected));
|
||||
}
|
||||
|
||||
function selectedScheduleVersion() {
|
||||
return scheduleVersions.find(version => String(version.id) === String(scheduleVersionSelect?.value)) || null;
|
||||
}
|
||||
|
||||
function syncRuleSemesterWithVersion() {
|
||||
const version = selectedScheduleVersion();
|
||||
if (!version) return;
|
||||
ruleSemesterSelect.value = String(version.semesterId);
|
||||
ruleSemesterSelect.disabled = true;
|
||||
syncSelects(ruleSemesterSelect);
|
||||
}
|
||||
|
||||
function setRuleEditorEnabled(enabled) {
|
||||
document.getElementById('schedule-rule-editor')?.classList.toggle('is-disabled', !enabled);
|
||||
ruleForm.querySelectorAll('input, select, button').forEach(control => {
|
||||
control.disabled = !enabled;
|
||||
});
|
||||
if (enabled) ruleSemesterSelect.disabled = true;
|
||||
}
|
||||
|
||||
async function loadRules() {
|
||||
rulesTbody.innerHTML = '<tr><td colspan="7" class="loading-row">Загрузка...</td></tr>';
|
||||
const version = selectedScheduleVersion();
|
||||
if (!version) {
|
||||
rules = [];
|
||||
rulesTbody.innerHTML = '<tr><td colspan="7" class="loading-row">Создайте черновик в разделе «Версии расписания»</td></tr>';
|
||||
setVisualState('Нет выбранного черновика');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
rules = await api.get('/api/admin/schedule-rules');
|
||||
rules = await api.get(`/api/admin/schedule-rules?versionId=${encodeURIComponent(version.id)}`);
|
||||
if (!visualPeriodTouched) {
|
||||
selectDefaultVisualPeriod();
|
||||
}
|
||||
@@ -1244,6 +1314,7 @@ export async function initSchedule() {
|
||||
id: Number(rule.id),
|
||||
subjectId: Number(rule.subjectId),
|
||||
semesterId: Number(rule.semesterId),
|
||||
scheduleVersionId: Number(rule.scheduleVersionId || scheduleVersionSelect.value),
|
||||
lectureAcademicHours: Number(rule.lectureAcademicHours || 0),
|
||||
laboratoryAcademicHours: Number(rule.laboratoryAcademicHours || 0),
|
||||
practiceAcademicHours: Number(rule.practiceAcademicHours || 0),
|
||||
@@ -1319,6 +1390,7 @@ export async function initSchedule() {
|
||||
const groupIds = selectedRuleGroupIds();
|
||||
const slots = readRuleSlots(true);
|
||||
if (!ruleSubjectSelect.value) throw new Error('Выберите дисциплину');
|
||||
if (!scheduleVersionSelect.value) throw new Error('Выберите черновик расписания');
|
||||
if (!ruleSemesterSelect.value) throw new Error('Выберите семестр');
|
||||
const typeLimits = readTypeLimits();
|
||||
validateTypeLimits(typeLimits, slots);
|
||||
@@ -1328,6 +1400,7 @@ export async function initSchedule() {
|
||||
id: ruleIdInput.value ? Number(ruleIdInput.value) : null,
|
||||
subjectId: Number(ruleSubjectSelect.value),
|
||||
semesterId: Number(ruleSemesterSelect.value),
|
||||
scheduleVersionId: Number(scheduleVersionSelect.value),
|
||||
...typeLimits,
|
||||
groupIds,
|
||||
slots
|
||||
@@ -1343,6 +1416,7 @@ export async function initSchedule() {
|
||||
syncSelects(ruleSubjectSelect, ruleSemesterSelect);
|
||||
renderRuleGroups(rule.groupIds || []);
|
||||
renderRuleSlots(rule.slots && rule.slots.length ? rule.slots : [{}]);
|
||||
syncRuleSemesterWithVersion();
|
||||
hideAlert('schedule-rule-alert');
|
||||
ruleForm.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}
|
||||
@@ -1354,6 +1428,7 @@ export async function initSchedule() {
|
||||
fillTypeLimits({});
|
||||
renderRuleGroups([]);
|
||||
renderRuleSlots([{}]);
|
||||
syncRuleSemesterWithVersion();
|
||||
syncSelects(ruleSubjectSelect, ruleSemesterSelect);
|
||||
hideAlert('schedule-rule-alert');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user