feat: добавлена навигация по неделям с возможностью отключения через админ-панель
feat: добавлена навигация по неделям с возможностью отключения через админ-панель Реализована навигация по неделям в расписании с парсингом ссылок из HTML страницы оригинального сайта. Добавлена возможность управления навигацией через админ-панель с сохранением настроек в файл. Основные изменения: - Парсинг навигации по неделям: * Добавлены типы WeekInfo и ParseResult в парсер * Реализована функция parseWeekNavigation для извлечения ссылок с параметром wk * Парсер ищет ссылки в href, onclick, формах и других атрибутах * Автоматическое определение номеров недель из текста ссылок и контекста * Вычисление соседних недель на основе найденных данных - API и функции: * Обновлена функция getSchedule для поддержки параметра wk в URL * Обновлен getServerSideProps для чтения параметра wk из query string * Кэширование расписания с учетом недели (ключ включает group + wk) - Компоненты: * Создан компонент WeekNavigation с кнопками навигации * Интегрирована навигация в компонент Schedule * Навигация работает через изменение URL параметра wk - Система настроек: * Создан settings-loader для загрузки/сохранения настроек в JSON * Добавлен API endpoint /api/admin/settings для управления настройками * Добавлен переключатель в админ-панели для включения/выключения навигации * Настройки сохраняются в src/shared/data/settings.json и переживают перезапуски - Файлы: * src/app/parser/schedule.ts - парсинг навигации по неделям * src/app/agregator/schedule.ts - поддержка параметра wk * src/pages/[group].tsx - чтение wk из query и передача настроек * src/widgets/schedule/week-navigation.tsx - компонент навигации * src/widgets/schedule/index.tsx - интеграция навигации * src/pages/admin.tsx - управление настройками * src/shared/data/settings-loader.ts - загрузка/сохранение настроек * src/pages/api/admin/settings.ts - API для настроек * src/shared/data/settings.json - файл с настройками
This commit is contained in:
@@ -1,21 +1,33 @@
|
||||
import { Day } from '@/shared/model/day'
|
||||
import { parsePage } from '@/app/parser/schedule'
|
||||
import { parsePage, ParseResult, WeekInfo } from '@/app/parser/schedule'
|
||||
import contentTypeParser from 'content-type'
|
||||
import { JSDOM } from 'jsdom'
|
||||
// import { content as mockContent } from './mock'
|
||||
import { reportParserError } from '@/app/logger'
|
||||
import { PROXY_URL } from '@/shared/constants/urls'
|
||||
|
||||
export type ScheduleResult = {
|
||||
days: Day[]
|
||||
currentWk?: number
|
||||
availableWeeks?: WeekInfo[]
|
||||
}
|
||||
|
||||
// ПС-7: 146
|
||||
export async function getSchedule(groupID: number, groupName: string): Promise<Day[]> {
|
||||
const page = await fetch(`${PROXY_URL}/?mn=2&obj=${groupID}`)
|
||||
export async function getSchedule(groupID: number, groupName: string, wk?: number): Promise<ScheduleResult> {
|
||||
const url = `${PROXY_URL}/?mn=2&obj=${groupID}${wk ? `&wk=${wk}` : ''}`
|
||||
const page = await fetch(url)
|
||||
// const page = { text: async () => mockContent, status: 200, headers: { get: (s: string) => s && 'text/html' } }
|
||||
const content = await page.text()
|
||||
const contentType = page.headers.get('content-type')
|
||||
if (page.status === 200 && contentType && contentTypeParser.parse(contentType).type === 'text/html') {
|
||||
try {
|
||||
const root = new JSDOM(content).window.document
|
||||
return parsePage(root, groupName)
|
||||
const root = new JSDOM(content, { url }).window.document
|
||||
const result = parsePage(root, groupName, url)
|
||||
return {
|
||||
days: result.days,
|
||||
currentWk: result.currentWk || wk,
|
||||
availableWeeks: result.availableWeeks
|
||||
}
|
||||
} catch(e) {
|
||||
console.error(`Error while parsing ${PROXY_URL}`)
|
||||
reportParserError(new Date().toISOString(), 'Не удалось сделать парсинг для группы', groupName)
|
||||
|
||||
Reference in New Issue
Block a user